Migrate to new pipe APIs (#2124)
This commit is contained in:
parent
53b4697269
commit
73a37363e1
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -22,8 +23,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var pipeFactory = new PipeFactory();
|
||||
var pair = pipeFactory.CreateConnectionPair();
|
||||
var bufferPool = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(bufferPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = pipeFactory,
|
||||
BufferPool = bufferPool,
|
||||
TimeoutControl = new MockTimeoutControl(),
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
|
@ -93,31 +94,34 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
private TestHttp1Connection<object> MakeHttp1Connection()
|
||||
{
|
||||
var pipeFactory = new PipeFactory();
|
||||
var pair = pipeFactory.CreateConnectionPair();
|
||||
_pair = pair;
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
using (var memoryPool = new MemoryPool())
|
||||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
Log = new MockTrace(),
|
||||
HttpParserFactory = f => new HttpParser<Http1ParsingHandler>()
|
||||
};
|
||||
var pair = PipeFactory.CreateConnectionPair(memoryPool);
|
||||
_pair = pair;
|
||||
|
||||
var http1Connection = new TestHttp1Connection<object>(application: null, context: new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = pipeFactory,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
Log = new MockTrace(),
|
||||
HttpParserFactory = f => new HttpParser<Http1ParsingHandler>()
|
||||
};
|
||||
|
||||
http1Connection.Reset();
|
||||
http1Connection.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
|
||||
var http1Connection = new TestHttp1Connection<object>(
|
||||
application: null, context: new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
BufferPool = memoryPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
|
||||
return http1Connection;
|
||||
http1Connection.Reset();
|
||||
http1Connection.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
|
||||
|
||||
return http1Connection;
|
||||
}
|
||||
}
|
||||
|
||||
[IterationCleanup]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -77,8 +78,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
public HttpProtocolFeatureCollection()
|
||||
{
|
||||
var pipeFactory = new PipeFactory();
|
||||
var pair = pipeFactory.CreateConnectionPair();
|
||||
var bufferPool = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(bufferPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -92,7 +93,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = pipeFactory,
|
||||
BufferPool = bufferPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
|
@ -14,13 +15,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
private const int InnerLoopCount = 512;
|
||||
|
||||
private IPipe _pipe;
|
||||
private PipeFactory _pipelineFactory;
|
||||
private BufferPool _bufferPool;
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_pipelineFactory = new PipeFactory();
|
||||
_pipe = _pipelineFactory.Create();
|
||||
_bufferPool = new MemoryPool();
|
||||
_pipe = new Pipe(new PipeOptions(_bufferPool));
|
||||
}
|
||||
|
||||
[Benchmark(OperationsPerInvoke = InnerLoopCount)]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -18,13 +19,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
|
||||
public Http1Connection<object> Http1Connection { get; set; }
|
||||
|
||||
public PipeFactory PipeFactory { get; set; }
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var pipeFactory = new PipeFactory();
|
||||
var pair = pipeFactory.CreateConnectionPair();
|
||||
var bufferPool = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(bufferPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -38,7 +37,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = pipeFactory,
|
||||
BufferPool = bufferPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport,
|
||||
TimeoutControl = new MockTimeoutControl()
|
||||
|
|
@ -47,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
http1Connection.Reset();
|
||||
|
||||
Http1Connection = http1Connection;
|
||||
Pipe = pipeFactory.Create();
|
||||
Pipe = new Pipe(new PipeOptions(bufferPool));
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
|
@ -170,8 +171,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var pipeFactory = new PipeFactory();
|
||||
var pair = pipeFactory.CreateConnectionPair();
|
||||
var bufferPool = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(bufferPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -185,7 +186,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = pipeFactory,
|
||||
BufferPool = bufferPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
|
@ -110,8 +111,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var pipeFactory = new PipeFactory();
|
||||
var pair = pipeFactory.CreateConnectionPair();
|
||||
var bufferPool = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(bufferPool);
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -121,15 +122,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
HttpParserFactory = f => new HttpParser<Http1ParsingHandler>()
|
||||
};
|
||||
|
||||
var http1Connection = new TestHttp1Connection<object>(application: null, context: new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = pipeFactory,
|
||||
TimeoutControl = new MockTimeoutControl(),
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
var http1Connection = new TestHttp1Connection<object>(
|
||||
application: null, context: new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
BufferPool = bufferPool,
|
||||
TimeoutControl = new MockTimeoutControl(),
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
});
|
||||
|
||||
http1Connection.Reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@
|
|||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
|
||||
<SystemBuffersPackageVersion>4.4.0</SystemBuffersPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>0.1.0-e170811-6</SystemIOPipelinesPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.4.0-preview3-25519-03</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.4.0</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.4.0</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>0.1.0-alpha-002</SystemIOPipelinesPackageVersion>
|
||||
<SystemIOPipelinesTestingPackageVersion>0.1.0-alpha-002</SystemIOPipelinesTestingPackageVersion>
|
||||
<SystemMemoryPackageVersion>4.5.0-preview1-25902-08</SystemMemoryPackageVersion>
|
||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview1-25902-08</SystemNumericsVectorsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-25902-08</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.4.0</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e170811-6</SystemTextEncodingsWebUtf8PackageVersion>
|
||||
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-alpha-002</SystemTextEncodingsWebUtf8PackageVersion>
|
||||
<SystemThreadingTasksExtensionsPackageVersion>4.4.0</SystemThreadingTasksExtensionsPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.7.0</XunitAnalyzersPackageVersion>
|
||||
<XunitPackageVersion>2.3.0</XunitPackageVersion>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
version:2.1.0-preview1-15549
|
||||
commithash:f570e08585fec510dd60cd4bfe8795388b757a95
|
||||
version:2.1.0-preview1-15551
|
||||
commithash:8fad9553b48533fddbb16a423ea55b9710ea2e63
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Protocols;
|
||||
|
|
@ -34,10 +36,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
|
||||
// REVIEW: Unfortunately, we still need to use the service context to create the pipes since the settings
|
||||
// for the scheduler and limits are specified here
|
||||
var inputOptions = GetInputPipeOptions(_serviceContext, transportFeature.InputWriterScheduler);
|
||||
var outputOptions = GetOutputPipeOptions(_serviceContext, transportFeature.OutputReaderScheduler);
|
||||
var inputOptions = GetInputPipeOptions(_serviceContext, connectionContext.BufferPool, transportFeature.InputWriterScheduler);
|
||||
var outputOptions = GetOutputPipeOptions(_serviceContext, connectionContext.BufferPool, transportFeature.OutputReaderScheduler);
|
||||
|
||||
var pair = connectionContext.PipeFactory.CreateConnectionPair(inputOptions, outputOptions);
|
||||
var pair = PipeFactory.CreateConnectionPair(inputOptions, outputOptions);
|
||||
|
||||
// Set the transport and connection id
|
||||
connectionContext.ConnectionId = CorrelationIdGenerator.GetNextId();
|
||||
|
|
@ -81,21 +83,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, IScheduler writerScheduler) => new PipeOptions
|
||||
{
|
||||
ReaderScheduler = serviceContext.ThreadPool,
|
||||
WriterScheduler = writerScheduler,
|
||||
MaximumSizeHigh = serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
MaximumSizeLow = serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
};
|
||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, BufferPool bufferPool, IScheduler writerScheduler) => new PipeOptions
|
||||
(
|
||||
bufferPool: bufferPool,
|
||||
readerScheduler: serviceContext.ThreadPool,
|
||||
writerScheduler: writerScheduler,
|
||||
maximumSizeHigh: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
);
|
||||
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, IScheduler readerScheduler) => new PipeOptions
|
||||
{
|
||||
ReaderScheduler = readerScheduler,
|
||||
WriterScheduler = serviceContext.ThreadPool,
|
||||
MaximumSizeHigh = GetOutputResponseBufferSize(serviceContext),
|
||||
MaximumSizeLow = GetOutputResponseBufferSize(serviceContext)
|
||||
};
|
||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, BufferPool bufferPool, IScheduler readerScheduler) => new PipeOptions
|
||||
(
|
||||
bufferPool: bufferPool,
|
||||
readerScheduler: readerScheduler,
|
||||
writerScheduler: serviceContext.ThreadPool,
|
||||
maximumSizeHigh: GetOutputResponseBufferSize(serviceContext),
|
||||
maximumSizeLow: GetOutputResponseBufferSize(serviceContext)
|
||||
);
|
||||
|
||||
private static long GetOutputResponseBufferSize(ServiceContext serviceContext)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -209,7 +209,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
if (pathEncoded)
|
||||
{
|
||||
// URI was encoded, unescape and then parse as UTF-8
|
||||
// Disabling warning temporary
|
||||
#pragma warning disable 618
|
||||
var pathLength = UrlEncoder.Decode(path, path);
|
||||
#pragma warning restore 618
|
||||
|
||||
// Removing dot segments must be done after unescaping. From RFC 3986:
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
public string ConnectionId { get; set; }
|
||||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public PipeFactory PipeFactory { get; set; }
|
||||
public BufferPool BufferPool { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public ITimeoutControl TimeoutControl { get; set; }
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
CancellationToken cancellationToken)
|
||||
{
|
||||
var writableBuffer = default(WritableBuffer);
|
||||
|
||||
long bytesWritten = 0;
|
||||
lock (_contextLock)
|
||||
{
|
||||
if (_completed)
|
||||
|
|
@ -181,17 +181,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
if (buffer.Count > 0)
|
||||
{
|
||||
writer.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||
bytesWritten += buffer.Count;
|
||||
}
|
||||
|
||||
writableBuffer.Commit();
|
||||
}
|
||||
|
||||
return FlushAsync(writableBuffer, cancellationToken);
|
||||
return FlushAsync(writableBuffer, bytesWritten, cancellationToken);
|
||||
}
|
||||
|
||||
// Single caller, at end of method - so inline
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Task FlushAsync(WritableBuffer writableBuffer, CancellationToken cancellationToken)
|
||||
private Task FlushAsync(WritableBuffer writableBuffer, long bytesWritten, CancellationToken cancellationToken)
|
||||
{
|
||||
var awaitable = writableBuffer.FlushAsync(cancellationToken);
|
||||
if (awaitable.IsCompleted)
|
||||
|
|
@ -199,7 +200,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
// The flush task can't fail today
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
return FlushAsyncAwaited(awaitable, writableBuffer.BytesWritten, cancellationToken);
|
||||
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task FlushAsyncAwaited(WritableBufferAwaitable awaitable, long count, CancellationToken cancellationToken)
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
public IHttpResponseControl HttpResponseControl { get; set; }
|
||||
|
||||
public IPipe RequestBodyPipe { get; }
|
||||
public Pipe RequestBodyPipe { get; }
|
||||
|
||||
public ServiceContext ServiceContext => _context.ServiceContext;
|
||||
private IPEndPoint LocalEndPoint => _context.LocalEndPoint;
|
||||
|
|
@ -1301,13 +1301,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
Log.ApplicationError(ConnectionId, TraceIdentifier, ex);
|
||||
}
|
||||
|
||||
private IPipe CreateRequestBodyPipe()
|
||||
=> _context.PipeFactory.Create(new PipeOptions
|
||||
{
|
||||
ReaderScheduler = ServiceContext.ThreadPool,
|
||||
WriterScheduler = InlineScheduler.Default,
|
||||
MaximumSizeHigh = 1,
|
||||
MaximumSizeLow = 1
|
||||
});
|
||||
private Pipe CreateRequestBodyPipe()
|
||||
=> new Pipe(new PipeOptions
|
||||
(
|
||||
bufferPool: _context.BufferPool,
|
||||
readerScheduler: ServiceContext.ThreadPool,
|
||||
writerScheduler: InlineScheduler.Default,
|
||||
maximumSizeHigh: 1,
|
||||
maximumSizeLow: 1
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
string ConnectionId { get; set; }
|
||||
ServiceContext ServiceContext { get; set; }
|
||||
IFeatureCollection ConnectionFeatures { get; set; }
|
||||
PipeFactory PipeFactory { get; set; }
|
||||
BufferPool BufferPool { get; set; }
|
||||
IPEndPoint RemoteEndPoint { get; set; }
|
||||
IPEndPoint LocalEndPoint { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
public static ArraySegment<byte> GetArray(this Buffer<byte> buffer)
|
||||
public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
|
||||
{
|
||||
ArraySegment<byte> result;
|
||||
if (!buffer.TryGetArray(out result))
|
||||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return result;
|
||||
}
|
||||
|
||||
public unsafe static void WriteAsciiNoValidation(ref WritableBufferWriter buffer, string data)
|
||||
public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe static void WriteNumeric(ref WritableBufferWriter buffer, ulong number)
|
||||
public unsafe static void WriteNumeric(ref this WritableBufferWriter buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void WriteNumericMultiWrite(ref WritableBufferWriter buffer, ulong number)
|
||||
private static void WriteNumericMultiWrite(ref this WritableBufferWriter buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private unsafe static void WriteAsciiMultiWrite(ref WritableBufferWriter buffer, string data)
|
||||
private unsafe static void WriteAsciiMultiWrite(ref this WritableBufferWriter buffer, string data)
|
||||
{
|
||||
var remaining = data.Length;
|
||||
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
StreamId = _incomingFrame.StreamId,
|
||||
ServiceContext = _context.ServiceContext,
|
||||
ConnectionFeatures = _context.ConnectionFeatures,
|
||||
PipeFactory = _context.PipeFactory,
|
||||
BufferPool = _context.BufferPool,
|
||||
LocalEndPoint = _context.LocalEndPoint,
|
||||
RemoteEndPoint = _context.RemoteEndPoint,
|
||||
StreamLifetimeHandler = this,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
public string ConnectionId { get; set; }
|
||||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public PipeFactory PipeFactory { get; set; }
|
||||
public BufferPool BufferPool { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
|||
public int StreamId { get; set; }
|
||||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public PipeFactory PipeFactory { get; set; }
|
||||
public BufferPool BufferPool { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IHttp2StreamLifetimeHandler StreamLifetimeHandler { get; set; }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
|
@ -65,24 +66,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
public IPEndPoint LocalEndPoint => _context.LocalEndPoint;
|
||||
public IPEndPoint RemoteEndPoint => _context.RemoteEndPoint;
|
||||
|
||||
private PipeFactory PipeFactory => _context.PipeFactory;
|
||||
private BufferPool BufferPool => _context.BufferPool;
|
||||
|
||||
// Internal for testing
|
||||
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _context.ServiceContext.ThreadPool,
|
||||
WriterScheduler = InlineScheduler.Default,
|
||||
MaximumSizeHigh = _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
MaximumSizeLow = _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
};
|
||||
(
|
||||
bufferPool: BufferPool,
|
||||
readerScheduler: _context.ServiceContext.ThreadPool,
|
||||
writerScheduler: InlineScheduler.Default,
|
||||
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||
);
|
||||
|
||||
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
|
||||
{
|
||||
ReaderScheduler = InlineScheduler.Default,
|
||||
WriterScheduler = InlineScheduler.Default,
|
||||
MaximumSizeHigh = _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||
MaximumSizeLow = _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
||||
};
|
||||
(
|
||||
bufferPool: BufferPool,
|
||||
readerScheduler: InlineScheduler.Default,
|
||||
writerScheduler: InlineScheduler.Default,
|
||||
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
||||
);
|
||||
|
||||
private IKestrelTrace Log => _context.ServiceContext.Log;
|
||||
|
||||
|
|
@ -107,8 +110,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
{
|
||||
adaptedPipeline = new AdaptedPipeline(transport,
|
||||
application,
|
||||
PipeFactory.Create(AdaptedInputPipeOptions),
|
||||
PipeFactory.Create(AdaptedOutputPipeOptions));
|
||||
new Pipe(AdaptedInputPipeOptions),
|
||||
new Pipe(AdaptedOutputPipeOptions));
|
||||
|
||||
transport = adaptedPipeline;
|
||||
}
|
||||
|
|
@ -180,7 +183,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
{
|
||||
ConnectionId = _context.ConnectionId,
|
||||
ConnectionFeatures = _context.ConnectionFeatures,
|
||||
PipeFactory = PipeFactory,
|
||||
BufferPool = BufferPool,
|
||||
LocalEndPoint = LocalEndPoint,
|
||||
RemoteEndPoint = RemoteEndPoint,
|
||||
ServiceContext = _context.ServiceContext,
|
||||
|
|
@ -197,7 +200,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
ConnectionId = _context.ConnectionId,
|
||||
ServiceContext = _context.ServiceContext,
|
||||
ConnectionFeatures = _context.ConnectionFeatures,
|
||||
PipeFactory = PipeFactory,
|
||||
BufferPool = BufferPool,
|
||||
LocalEndPoint = LocalEndPoint,
|
||||
RemoteEndPoint = RemoteEndPoint,
|
||||
Application = application,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
|
|
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
public ServiceContext ServiceContext { get; set; }
|
||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||
public IList<IConnectionAdapter> ConnectionAdapters { get; set; }
|
||||
public PipeFactory PipeFactory { get; set; }
|
||||
public BufferPool BufferPool { get; set; }
|
||||
public IPEndPoint LocalEndPoint { get; set; }
|
||||
public IPEndPoint RemoteEndPoint { get; set; }
|
||||
public IPipeConnection Transport { get; set; }
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
Protocols = _protocols,
|
||||
ServiceContext = _serviceContext,
|
||||
ConnectionFeatures = connectionContext.Features,
|
||||
PipeFactory = connectionContext.PipeFactory,
|
||||
BufferPool = connectionContext.BufferPool,
|
||||
ConnectionAdapters = _connectionAdapters,
|
||||
Transport = connectionContext.Transport,
|
||||
Application = transportFeature.Application
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -95,7 +96,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|||
set => LocalPort = value;
|
||||
}
|
||||
|
||||
PipeFactory IConnectionTransportFeature.PipeFactory => PipeFactory;
|
||||
BufferPool IConnectionTransportFeature.BufferPool => BufferPool;
|
||||
|
||||
IPipeConnection IConnectionTransportFeature.Transport
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
||||
{
|
||||
|
|
@ -20,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|||
|
||||
public string ConnectionId { get; set; }
|
||||
|
||||
public virtual PipeFactory PipeFactory { get; }
|
||||
public virtual BufferPool BufferPool { get; }
|
||||
public virtual IScheduler InputWriterScheduler { get; }
|
||||
public virtual IScheduler OutputReaderScheduler { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
private readonly UvStreamHandle _socket;
|
||||
|
||||
private WritableBuffer? _currentWritableBuffer;
|
||||
private BufferHandle _bufferHandle;
|
||||
private MemoryHandle _bufferHandle;
|
||||
|
||||
public LibuvConnection(ListenerContext context, UvStreamHandle socket) : base(context)
|
||||
{
|
||||
|
|
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
_bufferHandle = currentWritableBuffer.Buffer.Retain(true);
|
||||
|
||||
return handle.Libuv.buf_init((IntPtr)_bufferHandle.PinnedPointer, currentWritableBuffer.Buffer.Length);
|
||||
return handle.Libuv.buf_init((IntPtr)_bufferHandle.Pointer, currentWritableBuffer.Buffer.Length);
|
||||
}
|
||||
|
||||
private static void ReadCallback(UvStreamHandle handle, int status, object state)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Net;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
|
|
@ -15,8 +17,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
}
|
||||
|
||||
public ListenerContext ListenerContext { get; set; }
|
||||
|
||||
public override PipeFactory PipeFactory => ListenerContext.Thread.PipeFactory;
|
||||
|
||||
public override BufferPool BufferPool => ListenerContext.Thread.BufferPool;
|
||||
public override IScheduler InputWriterScheduler => ListenerContext.Thread;
|
||||
public override IScheduler OutputReaderScheduler => ListenerContext.Thread;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -55,7 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
#endif
|
||||
QueueCloseHandle = PostCloseHandle;
|
||||
QueueCloseAsyncHandle = EnqueueCloseHandle;
|
||||
PipeFactory = new PipeFactory();
|
||||
BufferPool = new MemoryPool();
|
||||
WriteReqPool = new WriteReqPool(this, _log);
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
public UvLoopHandle Loop { get { return _loop; } }
|
||||
|
||||
public PipeFactory PipeFactory { get; }
|
||||
public BufferPool BufferPool { get; }
|
||||
|
||||
public WriteReqPool WriteReqPool { get; }
|
||||
|
||||
|
|
@ -295,7 +296,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
PipeFactory.Dispose();
|
||||
BufferPool.Dispose();
|
||||
WriteReqPool.Dispose();
|
||||
_threadTcs.SetResult(null);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
|
||||
private LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>();
|
||||
private List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1);
|
||||
private List<BufferHandle> _handles = new List<BufferHandle>(BUFFER_COUNT + 1);
|
||||
private List<MemoryHandle> _handles = new List<MemoryHandle>(BUFFER_COUNT + 1);
|
||||
|
||||
public UvWriteReq(ILibuvTrace logger) : base(logger)
|
||||
{
|
||||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
|
||||
// Fast path for single buffer
|
||||
pBuffers[0] = Libuv.buf_init(
|
||||
(IntPtr)memoryHandle.PinnedPointer,
|
||||
(IntPtr)memoryHandle.Pointer,
|
||||
memory.Length);
|
||||
}
|
||||
else
|
||||
|
|
@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
|
||||
// create and pin each segment being written
|
||||
pBuffers[index] = Libuv.buf_init(
|
||||
(IntPtr)memoryHandle.PinnedPointer,
|
||||
(IntPtr)memoryHandle.Pointer,
|
||||
memory.Length);
|
||||
index++;
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
}
|
||||
|
||||
// Safe handle has instance method called Unpin
|
||||
// so using UnpinGcHandles to avoid conflict
|
||||
// so using UnpinGcHandles to avoid conflict
|
||||
private void UnpinGcHandles()
|
||||
{
|
||||
var pinList = _pins;
|
||||
|
|
@ -254,4 +254,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
{
|
||||
public static class BufferExtensions
|
||||
{
|
||||
public static ArraySegment<byte> GetArray(this Buffer<byte> buffer)
|
||||
public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
|
||||
{
|
||||
ArraySegment<byte> result;
|
||||
if (!buffer.TryGetArray(out result))
|
||||
|
|
@ -17,4 +17,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -9,6 +11,7 @@ using System.Net;
|
|||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Protocols;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
|
@ -25,14 +28,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
|
||||
private volatile bool _aborted;
|
||||
|
||||
internal SocketConnection(Socket socket, PipeFactory pipeFactory, ISocketsTrace trace)
|
||||
internal SocketConnection(Socket socket, BufferPool bufferPool, ISocketsTrace trace)
|
||||
{
|
||||
Debug.Assert(socket != null);
|
||||
Debug.Assert(pipeFactory != null);
|
||||
Debug.Assert(bufferPool != null);
|
||||
Debug.Assert(trace != null);
|
||||
|
||||
_socket = socket;
|
||||
PipeFactory = pipeFactory;
|
||||
BufferPool = bufferPool;
|
||||
_trace = trace;
|
||||
|
||||
var localEndPoint = (IPEndPoint)_socket.LocalEndPoint;
|
||||
|
|
@ -48,7 +51,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
_sender = new SocketSender(_socket);
|
||||
}
|
||||
|
||||
public override PipeFactory PipeFactory { get; }
|
||||
public override BufferPool BufferPool { get; }
|
||||
public override IScheduler InputWriterScheduler => InlineScheduler.Default;
|
||||
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
_eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError);
|
||||
}
|
||||
|
||||
public SocketAwaitable ReceiveAsync(Buffer<byte> buffer)
|
||||
public SocketAwaitable ReceiveAsync(Memory<byte> buffer)
|
||||
{
|
||||
var segment = buffer.GetArray();
|
||||
|
||||
|
|
@ -33,4 +33,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
return _awaitable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
return _awaitable;
|
||||
}
|
||||
|
||||
private SocketAwaitable SendAsync(Buffer<byte> buffer)
|
||||
private SocketAwaitable SendAsync(Memory<byte> buffer)
|
||||
{
|
||||
var segment = buffer.GetArray();
|
||||
|
||||
|
|
@ -95,4 +95,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
|||
awaitable.Complete(e.BytesTransferred, e.SocketError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
|
|
@ -19,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
{
|
||||
internal sealed class SocketTransport : ITransport
|
||||
{
|
||||
private readonly PipeFactory _pipeFactory = new PipeFactory();
|
||||
private readonly BufferPool _bufferPool = new MemoryPool();
|
||||
private readonly IEndPointInformation _endPointInformation;
|
||||
private readonly IConnectionHandler _handler;
|
||||
private readonly IApplicationLifetime _appLifetime;
|
||||
|
|
@ -115,7 +116,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
|
||||
public Task StopAsync()
|
||||
{
|
||||
_pipeFactory.Dispose();
|
||||
_bufferPool.Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +131,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
var acceptSocket = await _listenSocket.AcceptAsync();
|
||||
acceptSocket.NoDelay = _endPointInformation.NoDelay;
|
||||
|
||||
var connection = new SocketConnection(acceptSocket, _pipeFactory, _trace);
|
||||
var connection = new SocketConnection(acceptSocket, _bufferPool, _trace);
|
||||
_ = connection.StartAsync(_handler);
|
||||
}
|
||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionReset)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -14,6 +15,6 @@ namespace Microsoft.AspNetCore.Protocols
|
|||
|
||||
public abstract IPipeConnection Transport { get; set; }
|
||||
|
||||
public abstract PipeFactory PipeFactory { get; }
|
||||
public abstract BufferPool BufferPool { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO.Pipelines;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Protocols.Features;
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ namespace Microsoft.AspNetCore.Protocols
|
|||
|
||||
public override IFeatureCollection Features => _features.Collection;
|
||||
|
||||
public override PipeFactory PipeFactory => ConnectionTransportFeature.PipeFactory;
|
||||
public override BufferPool BufferPool => ConnectionTransportFeature.BufferPool;
|
||||
|
||||
public override IPipeConnection Transport
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
using System.IO.Pipelines;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Protocols.Features
|
||||
{
|
||||
public interface IConnectionTransportFeature
|
||||
{
|
||||
PipeFactory PipeFactory { get; }
|
||||
BufferPool BufferPool { get; }
|
||||
|
||||
IPipeConnection Transport { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
namespace System.IO.Pipelines
|
||||
using System.Buffers;
|
||||
|
||||
namespace System.IO.Pipelines
|
||||
{
|
||||
public static class PipeFactoryExtensions
|
||||
public static class PipeFactory
|
||||
{
|
||||
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(this PipeFactory pipeFactory)
|
||||
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(BufferPool memoryPool)
|
||||
{
|
||||
return pipeFactory.CreateConnectionPair(new PipeOptions(), new PipeOptions());
|
||||
return CreateConnectionPair(new PipeOptions(memoryPool), new PipeOptions(memoryPool));
|
||||
}
|
||||
|
||||
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(this PipeFactory pipeFactory, PipeOptions inputOptions, PipeOptions outputOptions)
|
||||
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions)
|
||||
{
|
||||
var input = pipeFactory.Create(inputOptions);
|
||||
var output = pipeFactory.Create(outputOptions);
|
||||
var input = new Pipe(inputOptions);
|
||||
var output = new Pipe(outputOptions);
|
||||
|
||||
var transportToApplication = new PipeConnection(output.Reader, input.Writer);
|
||||
var applicationToTransport = new PipeConnection(input.Reader, output.Writer);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Protocols.Features;
|
||||
|
|
@ -51,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Set<IConnectionTransportFeature>(this);
|
||||
}
|
||||
|
||||
public PipeFactory PipeFactory { get; } = new PipeFactory();
|
||||
public BufferPool BufferPool { get; } = new MemoryPool();
|
||||
|
||||
public IPipeConnection Transport { get; set; }
|
||||
public IPipeConnection Application { get; set; }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
@ -32,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private readonly TestHttp1Connection<object> _http1Connection;
|
||||
private readonly ServiceContext _serviceContext;
|
||||
private readonly Http1ConnectionContext _http1ConnectionContext;
|
||||
private readonly PipeFactory _pipelineFactory;
|
||||
private readonly BufferPool _pipelineFactory;
|
||||
private ReadCursor _consumed;
|
||||
private ReadCursor _examined;
|
||||
private Mock<ITimeoutControl> _timeoutControl;
|
||||
|
|
@ -52,8 +53,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public Http1ConnectionTests()
|
||||
{
|
||||
_pipelineFactory = new PipeFactory();
|
||||
var pair = _pipelineFactory.CreateConnectionPair();
|
||||
_pipelineFactory = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(_pipelineFactory);
|
||||
|
||||
_transport = pair.Transport;
|
||||
_application = pair.Application;
|
||||
|
|
@ -64,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
ServiceContext = _serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = _pipelineFactory,
|
||||
BufferPool = _pipelineFactory,
|
||||
TimeoutControl = _timeoutControl.Object,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
@ -92,7 +93,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private static readonly byte[] _noData = new byte[0];
|
||||
private static readonly byte[] _maxData = Encoding.ASCII.GetBytes(new string('a', Http2Frame.MinAllowedMaxFrameSize));
|
||||
|
||||
private readonly PipeFactory _pipeFactory = new PipeFactory();
|
||||
private readonly BufferPool _bufferPool = new MemoryPool();
|
||||
private readonly (IPipeConnection Transport, IPipeConnection Application) _pair;
|
||||
private readonly TestApplicationErrorLogger _logger;
|
||||
private readonly Http2ConnectionContext _connectionContext;
|
||||
|
|
@ -121,7 +122,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public Http2ConnectionTests()
|
||||
{
|
||||
_pair = _pipeFactory.CreateConnectionPair();
|
||||
_pair = PipeFactory.CreateConnectionPair(_bufferPool);
|
||||
|
||||
_noopApplication = context => Task.CompletedTask;
|
||||
|
||||
|
|
@ -256,7 +257,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
Log = new TestKestrelTrace(_logger)
|
||||
},
|
||||
PipeFactory = _pipeFactory,
|
||||
BufferPool = _bufferPool,
|
||||
Application = _pair.Application,
|
||||
Transport = _pair.Transport
|
||||
};
|
||||
|
|
@ -265,7 +266,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_pipeFactory.Dispose();
|
||||
_bufferPool.Dispose();
|
||||
}
|
||||
|
||||
void IHttpHeadersHandler.OnHeader(Span<byte> name, Span<byte> value)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
|
|
@ -17,21 +18,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
public class HttpConnectionTests : IDisposable
|
||||
{
|
||||
private readonly PipeFactory _pipeFactory;
|
||||
private readonly BufferPool _bufferPool;
|
||||
private readonly HttpConnectionContext _httpConnectionContext;
|
||||
private readonly HttpConnection _httpConnection;
|
||||
|
||||
public HttpConnectionTests()
|
||||
{
|
||||
_pipeFactory = new PipeFactory();
|
||||
var pair = _pipeFactory.CreateConnectionPair();
|
||||
_bufferPool = new MemoryPool();
|
||||
var pair = PipeFactory.CreateConnectionPair(_bufferPool);
|
||||
|
||||
_httpConnectionContext = new HttpConnectionContext
|
||||
{
|
||||
ConnectionId = "0123456789",
|
||||
ConnectionAdapters = new List<IConnectionAdapter>(),
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = _pipeFactory,
|
||||
BufferPool = _bufferPool,
|
||||
HttpConnectionId = long.MinValue,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport,
|
||||
|
|
@ -46,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_pipeFactory.Dispose();
|
||||
_bufferPool.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO.Pipelines;
|
||||
|
|
@ -19,26 +20,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[Fact]
|
||||
public void InitialDictionaryIsEmpty()
|
||||
{
|
||||
var factory = new PipeFactory();
|
||||
var pair = factory.CreateConnectionPair();
|
||||
var http1ConnectionContext = new Http1ConnectionContext
|
||||
using (var memoryPool = new MemoryPool())
|
||||
{
|
||||
ServiceContext = new TestServiceContext(),
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = factory,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport,
|
||||
TimeoutControl = null
|
||||
};
|
||||
var pair = PipeFactory.CreateConnectionPair(memoryPool);
|
||||
var http1ConnectionContext = new Http1ConnectionContext
|
||||
{
|
||||
ServiceContext = new TestServiceContext(),
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
BufferPool = memoryPool,
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport,
|
||||
TimeoutControl = null
|
||||
};
|
||||
|
||||
var http1Connection = new Http1Connection<object>(application: null, context: http1ConnectionContext);
|
||||
var http1Connection = new Http1Connection<object>(application: null, context: http1ConnectionContext);
|
||||
|
||||
http1Connection.Reset();
|
||||
http1Connection.Reset();
|
||||
|
||||
IDictionary<string, StringValues> headers = http1Connection.ResponseHeaders;
|
||||
IDictionary<string, StringValues> headers = http1Connection.ResponseHeaders;
|
||||
|
||||
Assert.Equal(0, headers.Count);
|
||||
Assert.False(headers.IsReadOnly);
|
||||
Assert.Equal(0, headers.Count);
|
||||
Assert.False(headers.IsReadOnly);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
|
||||
<PackageReference Include="System.IO.Pipelines.Testing" Version="$(SystemIOPipelinesTestingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
|
@ -13,25 +15,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
public class OutputProducerTests : IDisposable
|
||||
{
|
||||
private readonly PipeFactory _pipeFactory;
|
||||
private readonly BufferPool _bufferPool;
|
||||
|
||||
public OutputProducerTests()
|
||||
{
|
||||
_pipeFactory = new PipeFactory();
|
||||
_bufferPool = new MemoryPool();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_pipeFactory.Dispose();
|
||||
_bufferPool.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WritesNoopAfterConnectionCloses()
|
||||
{
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = Mock.Of<IScheduler>(),
|
||||
};
|
||||
(
|
||||
bufferPool:_bufferPool,
|
||||
readerScheduler: Mock.Of<IScheduler>()
|
||||
);
|
||||
|
||||
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -52,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
private Http1OutputProducer CreateOutputProducer(PipeOptions pipeOptions)
|
||||
{
|
||||
var pipe = _pipeFactory.Create(pipeOptions);
|
||||
var pipe = new Pipe(pipeOptions);
|
||||
var serviceContext = new TestServiceContext();
|
||||
var socketOutput = new Http1OutputProducer(
|
||||
pipe.Reader,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
|
@ -25,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||
|
||||
var mockScheduler = Mock.Of<IScheduler>();
|
||||
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, readerScheduler: mockScheduler);
|
||||
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow);
|
||||
Assert.Equal(expectedMaximumSizeHigh, outputPipeOptions.MaximumSizeHigh);
|
||||
|
|
@ -43,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||
|
||||
var mockScheduler = Mock.Of<IScheduler>();
|
||||
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, writerScheduler: mockScheduler);
|
||||
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
|
||||
|
||||
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow);
|
||||
Assert.Equal(expectedMaximumSizeHigh, inputPipeOptions.MaximumSizeHigh);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
|
|
@ -15,16 +16,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
private const int _ulongMaxValueLength = 20;
|
||||
|
||||
private readonly IPipe _pipe;
|
||||
private readonly PipeFactory _pipeFactory = new PipeFactory();
|
||||
private readonly BufferPool _bufferPool = new MemoryPool();
|
||||
|
||||
public PipelineExtensionTests()
|
||||
{
|
||||
_pipe = _pipeFactory.Create();
|
||||
_pipe = new Pipe(new PipeOptions(_bufferPool));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_pipeFactory.Dispose();
|
||||
_bufferPool.Dispose();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
PipelineExtensions.WriteNumeric(ref writer, number);
|
||||
writer.WriteNumeric(number);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -57,7 +58,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
writer.Write(spacer);
|
||||
|
||||
var bufferLength = writer.Span.Length;
|
||||
PipelineExtensions.WriteNumeric(ref writer, ulong.MaxValue);
|
||||
writer.WriteNumeric(ulong.MaxValue);
|
||||
Assert.NotEqual(bufferLength, writer.Span.Length);
|
||||
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
|
@ -83,7 +84,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
{
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, input);
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -110,7 +111,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
// but it shouldn't produce more than one byte per character
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, input);
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -125,7 +126,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
for (var i = 0; i < maxAscii; i++)
|
||||
{
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, new string((char)i, 1));
|
||||
writer.WriteAsciiNoValidation(new string((char)i, 1));
|
||||
}
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -158,7 +159,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
Assert.Equal(gapSize, writer.Span.Length);
|
||||
|
||||
var bufferLength = writer.Span.Length;
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, testString);
|
||||
writer.WriteAsciiNoValidation(testString);
|
||||
Assert.NotEqual(bufferLength, writer.Span.Length);
|
||||
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -15,13 +16,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
class TestInput : IDisposable
|
||||
{
|
||||
private MemoryPool _memoryPool;
|
||||
private PipeFactory _pipelineFactory;
|
||||
|
||||
public TestInput()
|
||||
{
|
||||
_memoryPool = new MemoryPool();
|
||||
_pipelineFactory = new PipeFactory();
|
||||
var pair = _pipelineFactory.CreateConnectionPair();
|
||||
var pair = PipeFactory.CreateConnectionPair(_memoryPool);
|
||||
Transport = pair.Transport;
|
||||
Application = pair.Application;
|
||||
|
||||
|
|
@ -31,7 +30,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
ConnectionFeatures = new FeatureCollection(),
|
||||
Application = Application,
|
||||
Transport = Transport,
|
||||
PipeFactory = _pipelineFactory,
|
||||
BufferPool = _memoryPool,
|
||||
TimeoutControl = Mock.Of<ITimeoutControl>()
|
||||
};
|
||||
|
||||
|
|
@ -43,8 +42,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public IPipeConnection Application { get; }
|
||||
|
||||
public PipeFactory PipeFactory => _pipelineFactory;
|
||||
|
||||
public Http1ConnectionContext Http1ConnectionContext { get; }
|
||||
|
||||
public Http1Connection Http1Connection { get; set; }
|
||||
|
|
@ -67,7 +64,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_pipelineFactory.Dispose();
|
||||
_memoryPool.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,13 +55,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied()
|
||||
{
|
||||
var mockConnectionHandler = new MockConnectionHandler();
|
||||
mockConnectionHandler.InputOptions.MaximumSizeHigh = 3;
|
||||
var mockLibuv = new MockLibuv();
|
||||
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
|
||||
var transport = new LibuvTransport(mockLibuv, transportContext, null);
|
||||
var thread = new LibuvThread(transport);
|
||||
mockConnectionHandler.InputOptions = pool =>
|
||||
new PipeOptions(
|
||||
bufferPool: pool,
|
||||
maximumSizeHigh: 3);
|
||||
|
||||
// We don't set the output writer scheduler here since we want to run the callback inline
|
||||
mockConnectionHandler.OutputOptions.ReaderScheduler = thread;
|
||||
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(bufferPool: pool, readerScheduler: thread);
|
||||
|
||||
|
||||
Task connectionTask = null;
|
||||
try
|
||||
{
|
||||
|
|
@ -106,8 +113,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
public async Task ConnectionDoesNotResumeAfterReadCallbackScheduledAndSocketCloseIfBackpressureIsApplied()
|
||||
{
|
||||
var mockConnectionHandler = new MockConnectionHandler();
|
||||
mockConnectionHandler.InputOptions.MaximumSizeHigh = 3;
|
||||
mockConnectionHandler.InputOptions.MaximumSizeLow = 3;
|
||||
var mockLibuv = new MockLibuv();
|
||||
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
|
||||
var transport = new LibuvTransport(mockLibuv, transportContext, null);
|
||||
|
|
@ -118,8 +123,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
{
|
||||
backPressure = () => a(o);
|
||||
});
|
||||
mockConnectionHandler.InputOptions.WriterScheduler = mockScheduler.Object;
|
||||
mockConnectionHandler.OutputOptions.ReaderScheduler = thread;
|
||||
mockConnectionHandler.InputOptions = pool =>
|
||||
new PipeOptions(
|
||||
bufferPool: pool,
|
||||
maximumSizeHigh: 3,
|
||||
maximumSizeLow: 3,
|
||||
writerScheduler: mockScheduler.Object);
|
||||
|
||||
mockConnectionHandler.OutputOptions = pool => new PipeOptions(bufferPool: pool, readerScheduler:thread );
|
||||
|
||||
Task connectionTask = null;
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
|
|
@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
{
|
||||
public class LibuvOutputConsumerTests : IDisposable
|
||||
{
|
||||
private readonly PipeFactory _pipeFactory;
|
||||
private readonly BufferPool _bufferPool;
|
||||
private readonly MockLibuv _mockLibuv;
|
||||
private readonly LibuvThread _libuvThread;
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
|
||||
public LibuvOutputConsumerTests()
|
||||
{
|
||||
_pipeFactory = new PipeFactory();
|
||||
_bufferPool = new MemoryPool();
|
||||
_mockLibuv = new MockLibuv();
|
||||
|
||||
var libuvTransport = new LibuvTransport(_mockLibuv, new TestLibuvTransportContext(), new ListenOptions(0));
|
||||
|
|
@ -48,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
public void Dispose()
|
||||
{
|
||||
_libuvThread.StopAsync(TimeSpan.FromSeconds(1)).Wait();
|
||||
_pipeFactory.Dispose();
|
||||
_bufferPool.Dispose();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -62,11 +63,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize ?? 0,
|
||||
MaximumSizeLow = maxResponseBufferSize ?? 0,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize ?? 0,
|
||||
maximumSizeLow: maxResponseBufferSize ?? 0
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -97,11 +99,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = 0,
|
||||
MaximumSizeLow = 0,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: 0,
|
||||
maximumSizeLow: 0
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -144,11 +147,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
// ConnectionHandler will set MaximumSizeHigh/Low to 1 when MaxResponseBufferSize is zero.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = 1,
|
||||
MaximumSizeLow = 1,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: 1,
|
||||
maximumSizeLow: 1
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -199,11 +203,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
};
|
||||
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize,
|
||||
MaximumSizeLow = maxResponseBufferSize,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -262,11 +267,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
};
|
||||
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize,
|
||||
MaximumSizeLow = maxResponseBufferSize,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -331,11 +337,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
var abortedSource = new CancellationTokenSource();
|
||||
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize,
|
||||
MaximumSizeLow = maxResponseBufferSize,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource))
|
||||
{
|
||||
|
|
@ -423,11 +430,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
var abortedSource = new CancellationTokenSource();
|
||||
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize,
|
||||
MaximumSizeLow = maxResponseBufferSize,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -506,11 +514,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
var abortedSource = new CancellationTokenSource();
|
||||
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize,
|
||||
MaximumSizeLow = maxResponseBufferSize,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -587,11 +596,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
};
|
||||
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize,
|
||||
MaximumSizeLow = maxResponseBufferSize,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize,
|
||||
maximumSizeLow: maxResponseBufferSize
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -647,11 +657,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
|
||||
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
|
||||
var pipeOptions = new PipeOptions
|
||||
{
|
||||
ReaderScheduler = _libuvThread,
|
||||
MaximumSizeHigh = maxResponseBufferSize ?? 0,
|
||||
MaximumSizeLow = maxResponseBufferSize ?? 0,
|
||||
};
|
||||
(
|
||||
bufferPool: _bufferPool,
|
||||
readerScheduler: _libuvThread,
|
||||
maximumSizeHigh: maxResponseBufferSize ?? 0,
|
||||
maximumSizeLow: maxResponseBufferSize ?? 0
|
||||
);
|
||||
|
||||
using (var outputProducer = CreateOutputProducer(pipeOptions))
|
||||
{
|
||||
|
|
@ -684,7 +695,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
|
||||
private Http1OutputProducer CreateOutputProducer(PipeOptions pipeOptions, CancellationTokenSource cts = null)
|
||||
{
|
||||
var pair = _pipeFactory.CreateConnectionPair(pipeOptions, pipeOptions);
|
||||
var pair = PipeFactory.CreateConnectionPair(pipeOptions, pipeOptions);
|
||||
|
||||
var logger = new TestApplicationErrorLogger();
|
||||
var serviceContext = new TestServiceContext
|
||||
|
|
@ -701,7 +712,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
{
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
PipeFactory = _pipeFactory,
|
||||
BufferPool = _bufferPool,
|
||||
TimeoutControl = Mock.Of<ITimeoutControl>(),
|
||||
Application = pair.Application,
|
||||
Transport = pair.Transport
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -13,15 +14,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
|||
{
|
||||
public class MockConnectionHandler : IConnectionHandler
|
||||
{
|
||||
public PipeOptions InputOptions { get; set; } = new PipeOptions();
|
||||
public PipeOptions OutputOptions { get; set; } = new PipeOptions();
|
||||
public Func<BufferPool, PipeOptions> InputOptions { get; set; } = pool => new PipeOptions(pool);
|
||||
public Func<BufferPool, PipeOptions> OutputOptions { get; set; } = pool => new PipeOptions(pool);
|
||||
|
||||
public void OnConnection(IFeatureCollection features)
|
||||
{
|
||||
var connectionContext = new DefaultConnectionContext(features);
|
||||
|
||||
Input = connectionContext.PipeFactory.Create(InputOptions ?? new PipeOptions());
|
||||
Output = connectionContext.PipeFactory.Create(OutputOptions ?? new PipeOptions());
|
||||
Input = new Pipe(InputOptions(connectionContext.BufferPool));
|
||||
Output = new Pipe(InputOptions(connectionContext.BufferPool));
|
||||
|
||||
var feature = connectionContext.Features.Get<IConnectionTransportFeature>();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue