parent
b57ac72431
commit
1fa001e7db
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
{
|
{
|
||||||
private const int InnerLoopCount = 512;
|
private const int InnerLoopCount = 512;
|
||||||
|
|
||||||
public ReadableBuffer _buffer;
|
public ReadOnlyBuffer _buffer;
|
||||||
public Http1Connection _http1Connection;
|
public Http1Connection _http1Connection;
|
||||||
|
|
||||||
[IterationSetup]
|
[IterationSetup]
|
||||||
|
|
|
||||||
|
|
@ -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.Buffers;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
|
|
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
{
|
{
|
||||||
private readonly HttpParser<Adapter> _parser = new HttpParser<Adapter>();
|
private readonly HttpParser<Adapter> _parser = new HttpParser<Adapter>();
|
||||||
|
|
||||||
private ReadableBuffer _buffer;
|
private ReadOnlyBuffer _buffer;
|
||||||
|
|
||||||
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
|
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
|
||||||
public void PlaintextTechEmpower()
|
public void PlaintextTechEmpower()
|
||||||
|
|
@ -46,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
|
|
||||||
private void InsertData(byte[] data)
|
private void InsertData(byte[] data)
|
||||||
{
|
{
|
||||||
_buffer = ReadableBuffer.Create(data);
|
_buffer = new ReadOnlyBuffer(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseData()
|
private void ParseData()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// 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.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
|
|
@ -21,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
|
|
||||||
public static readonly NullParser<Http1ParsingHandler> Instance = new NullParser<Http1ParsingHandler>();
|
public static readonly NullParser<Http1ParsingHandler> Instance = new NullParser<Http1ParsingHandler>();
|
||||||
|
|
||||||
public bool ParseHeaders(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes)
|
public bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes)
|
||||||
{
|
{
|
||||||
handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
|
handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
|
||||||
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
|
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
|
||||||
|
|
@ -34,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ParseRequestLine(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
public bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
handler.OnStartLine(HttpMethod.Get,
|
handler.OnStartLine(HttpMethod.Get,
|
||||||
HttpVersion.Http11,
|
HttpVersion.Http11,
|
||||||
|
|
|
||||||
|
|
@ -25,20 +25,21 @@
|
||||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsLoggingTestingPackageVersion>
|
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsOptionsPackageVersion>
|
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsOptionsPackageVersion>
|
||||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||||
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview1-26016-05</MicrosoftNETCoreApp21PackageVersion>
|
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview1-26102-01</MicrosoftNETCoreApp21PackageVersion>
|
||||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview1-27965</MicrosoftNetHttpHeadersPackageVersion>
|
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview1-27965</MicrosoftNetHttpHeadersPackageVersion>
|
||||||
<MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion>
|
<MicrosoftNETTestSdkPackageVersion>15.3.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-preview1-26016-05</SystemBuffersPackageVersion>
|
<SystemBuffersPackageVersion>4.5.0-preview1-26102-01</SystemBuffersPackageVersion>
|
||||||
<SystemIOPipelinesPackageVersion>0.1.0-e171215-1</SystemIOPipelinesPackageVersion>
|
<SystemBuffersPrimitivesPackageVersion>0.1.0-e180104-2</SystemBuffersPrimitivesPackageVersion>
|
||||||
<SystemIOPipelinesTestingPackageVersion>0.1.0-e171215-1</SystemIOPipelinesTestingPackageVersion>
|
<SystemIOPipelinesPackageVersion>0.1.0-e180104-2</SystemIOPipelinesPackageVersion>
|
||||||
<SystemMemoryPackageVersion>4.5.0-preview1-26016-05</SystemMemoryPackageVersion>
|
<SystemIOPipelinesTestingPackageVersion>0.1.0-e180104-2</SystemIOPipelinesTestingPackageVersion>
|
||||||
<SystemNumericsVectorsPackageVersion>4.5.0-preview1-26016-05</SystemNumericsVectorsPackageVersion>
|
<SystemMemoryPackageVersion>4.5.0-preview1-26102-01</SystemMemoryPackageVersion>
|
||||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-26016-05</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
<SystemNumericsVectorsPackageVersion>4.5.0-preview1-26102-01</SystemNumericsVectorsPackageVersion>
|
||||||
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview1-26016-05</SystemSecurityCryptographyCngPackageVersion>
|
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-26102-01</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||||
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e171215-1</SystemTextEncodingsWebUtf8PackageVersion>
|
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview1-26102-01</SystemSecurityCryptographyCngPackageVersion>
|
||||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-25707-02</SystemThreadingTasksExtensionsPackageVersion>
|
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e180104-2</SystemTextEncodingsWebUtf8PackageVersion>
|
||||||
|
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview1-26102-01</SystemThreadingTasksExtensionsPackageVersion>
|
||||||
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
||||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||||
<XunitRunnerVisualStudioPackageVersion>2.3.1</XunitRunnerVisualStudioPackageVersion>
|
<XunitRunnerVisualStudioPackageVersion>2.3.1</XunitRunnerVisualStudioPackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, IScheduler writerScheduler) => new PipeOptions
|
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, Scheduler writerScheduler) => new PipeOptions
|
||||||
(
|
(
|
||||||
pool: memoryPool,
|
pool: memoryPool,
|
||||||
readerScheduler: serviceContext.ThreadPool,
|
readerScheduler: serviceContext.ThreadPool,
|
||||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||||
);
|
);
|
||||||
|
|
||||||
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, IScheduler readerScheduler) => new PipeOptions
|
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, Scheduler readerScheduler) => new PipeOptions
|
||||||
(
|
(
|
||||||
pool: memoryPool,
|
pool: memoryPool,
|
||||||
readerScheduler: readerScheduler,
|
readerScheduler: readerScheduler,
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,14 @@
|
||||||
// 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.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Encodings.Web.Utf8;
|
using System.Text.Encodings.Web.Utf8;
|
||||||
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
|
|
||||||
|
|
@ -66,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
Input.CancelPendingRead();
|
Input.CancelPendingRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParseRequest(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
public void ParseRequest(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = buffer.Start;
|
consumed = buffer.Start;
|
||||||
examined = buffer.End;
|
examined = buffer.End;
|
||||||
|
|
@ -104,7 +107,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TakeStartLine(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
public bool TakeStartLine(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
var overLength = false;
|
var overLength = false;
|
||||||
if (buffer.Length >= ServerOptions.Limits.MaxRequestLineSize)
|
if (buffer.Length >= ServerOptions.Limits.MaxRequestLineSize)
|
||||||
|
|
@ -122,7 +125,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TakeMessageHeaders(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
public bool TakeMessageHeaders(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
// Make sure the buffer is limited
|
// Make sure the buffer is limited
|
||||||
bool overLength = false;
|
bool overLength = false;
|
||||||
|
|
@ -424,7 +427,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest);
|
TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool BeginRead(out ReadableBufferAwaitable awaitable)
|
protected override bool BeginRead(out ValueAwaiter<ReadResult> awaitable)
|
||||||
{
|
{
|
||||||
awaitable = Input.ReadAsync();
|
awaitable = Input.ReadAsync();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// 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.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -149,7 +151,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Copy(ReadableBuffer readableBuffer, WritableBuffer writableBuffer)
|
protected void Copy(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer)
|
||||||
{
|
{
|
||||||
_context.TimeoutControl.BytesRead(readableBuffer.Length);
|
_context.TimeoutControl.BytesRead(readableBuffer.Length);
|
||||||
|
|
||||||
|
|
@ -171,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
_pumpTask = PumpAsync();
|
_pumpTask = PumpAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined)
|
protected virtual bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +298,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
RequestUpgrade = true;
|
RequestUpgrade = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined)
|
protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
Copy(readableBuffer, writableBuffer);
|
Copy(readableBuffer, writableBuffer);
|
||||||
consumed = readableBuffer.End;
|
consumed = readableBuffer.End;
|
||||||
|
|
@ -318,7 +320,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
_inputLength = _contentLength;
|
_inputLength = _contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined)
|
protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
if (_inputLength == 0)
|
if (_inputLength == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -366,10 +368,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
RequestKeepAlive = keepAlive;
|
RequestKeepAlive = keepAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined)
|
protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = default(ReadCursor);
|
consumed = default(Position);
|
||||||
examined = default(ReadCursor);
|
examined = default(Position);
|
||||||
|
|
||||||
while (_mode < Mode.Trailer)
|
while (_mode < Mode.Trailer)
|
||||||
{
|
{
|
||||||
|
|
@ -457,17 +459,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseChunkedPrefix(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
private void ParseChunkedPrefix(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = buffer.Start;
|
consumed = buffer.Start;
|
||||||
examined = buffer.Start;
|
examined = buffer.Start;
|
||||||
var reader = new ReadableBufferReader(buffer);
|
var reader = BufferReader.Create(buffer);
|
||||||
var ch1 = reader.Take();
|
var ch1 = reader.Take();
|
||||||
var ch2 = reader.Take();
|
var ch2 = reader.Take();
|
||||||
|
|
||||||
if (ch1 == -1 || ch2 == -1)
|
if (ch1 == -1 || ch2 == -1)
|
||||||
{
|
{
|
||||||
examined = reader.Cursor;
|
examined = reader.Position;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -478,8 +480,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
if (ch1 == ';')
|
if (ch1 == ';')
|
||||||
{
|
{
|
||||||
consumed = reader.Cursor;
|
consumed = reader.Position;
|
||||||
examined = reader.Cursor;
|
examined = reader.Position;
|
||||||
|
|
||||||
AddAndCheckConsumedBytes(reader.ConsumedBytes);
|
AddAndCheckConsumedBytes(reader.ConsumedBytes);
|
||||||
_inputLength = chunkSize;
|
_inputLength = chunkSize;
|
||||||
|
|
@ -490,14 +492,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
ch2 = reader.Take();
|
ch2 = reader.Take();
|
||||||
if (ch2 == -1)
|
if (ch2 == -1)
|
||||||
{
|
{
|
||||||
examined = reader.Cursor;
|
examined = reader.Position;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch1 == '\r' && ch2 == '\n')
|
if (ch1 == '\r' && ch2 == '\n')
|
||||||
{
|
{
|
||||||
consumed = reader.Cursor;
|
consumed = reader.Position;
|
||||||
examined = reader.Cursor;
|
examined = reader.Position;
|
||||||
|
|
||||||
AddAndCheckConsumedBytes(reader.ConsumedBytes);
|
AddAndCheckConsumedBytes(reader.ConsumedBytes);
|
||||||
_inputLength = chunkSize;
|
_inputLength = chunkSize;
|
||||||
|
|
@ -513,7 +515,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
_context.ThrowRequestRejected(RequestRejectionReason.BadChunkSizeData);
|
_context.ThrowRequestRejected(RequestRejectionReason.BadChunkSizeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseExtension(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
private void ParseExtension(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
// Chunk-extensions not currently parsed
|
// Chunk-extensions not currently parsed
|
||||||
// Just drain the data
|
// Just drain the data
|
||||||
|
|
@ -522,8 +524,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ReadCursor extensionCursor;
|
Position extensionCursor;
|
||||||
if (ReadCursorOperations.Seek(buffer.Start, buffer.End, out extensionCursor, ByteCR) == -1)
|
if (ReadOnlyBuffer.Seek(buffer.Start, buffer.End, out extensionCursor, ByteCR) == -1)
|
||||||
{
|
{
|
||||||
// End marker not found yet
|
// End marker not found yet
|
||||||
consumed = buffer.End;
|
consumed = buffer.End;
|
||||||
|
|
@ -565,7 +567,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
} while (_mode == Mode.Extension);
|
} while (_mode == Mode.Extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadChunkedData(ReadableBuffer buffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined)
|
private void ReadChunkedData(ReadOnlyBuffer buffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
var actual = Math.Min(buffer.Length, _inputLength);
|
var actual = Math.Min(buffer.Length, _inputLength);
|
||||||
consumed = buffer.Move(buffer.Start, actual);
|
consumed = buffer.Move(buffer.Start, actual);
|
||||||
|
|
@ -582,7 +584,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseChunkedSuffix(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
private void ParseChunkedSuffix(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = buffer.Start;
|
consumed = buffer.Start;
|
||||||
examined = buffer.Start;
|
examined = buffer.Start;
|
||||||
|
|
@ -608,7 +610,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseChunkedTrailer(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
private void ParseChunkedTrailer(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = buffer.Start;
|
consumed = buffer.Start;
|
||||||
examined = buffer.Start;
|
examined = buffer.Start;
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
|
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FlushAsyncAwaited(WritableBufferAwaitable awaitable, long count, CancellationToken cancellationToken)
|
private async Task FlushAsyncAwaited(ValueAwaiter<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
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// 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.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
@ -31,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
private const byte ByteQuestionMark = (byte)'?';
|
private const byte ByteQuestionMark = (byte)'?';
|
||||||
private const byte BytePercentage = (byte)'%';
|
private const byte BytePercentage = (byte)'%';
|
||||||
|
|
||||||
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = buffer.Start;
|
consumed = buffer.Start;
|
||||||
examined = buffer.End;
|
examined = buffer.End;
|
||||||
|
|
@ -186,7 +188,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
handler.OnStartLine(method, httpVersion, targetBuffer, pathBuffer, query, customMethod, pathEncoded);
|
handler.OnStartLine(method, httpVersion, targetBuffer, pathBuffer, query, customMethod, pathEncoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe bool ParseHeaders(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes)
|
public unsafe bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes)
|
||||||
{
|
{
|
||||||
consumed = buffer.Start;
|
consumed = buffer.Start;
|
||||||
examined = buffer.End;
|
examined = buffer.End;
|
||||||
|
|
@ -194,8 +196,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
||||||
var bufferEnd = buffer.End;
|
var bufferEnd = buffer.End;
|
||||||
|
|
||||||
var reader = new ReadableBufferReader(buffer);
|
var reader = BufferReader.Create(buffer);
|
||||||
var start = default(ReadableBufferReader);
|
var start = default(BufferReader<ReadOnlyBuffer>);
|
||||||
var done = false;
|
var done = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -276,10 +278,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var current = reader.Cursor;
|
var current = reader.Position;
|
||||||
|
|
||||||
// Split buffers
|
// Split buffers
|
||||||
if (ReadCursorOperations.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1)
|
if (ReadOnlyBuffer.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1)
|
||||||
{
|
{
|
||||||
// Not there
|
// Not there
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -312,7 +314,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
consumed = reader.Cursor;
|
consumed = reader.Position;
|
||||||
consumedBytes = reader.ConsumedBytes;
|
consumedBytes = reader.ConsumedBytes;
|
||||||
|
|
||||||
if (done)
|
if (done)
|
||||||
|
|
@ -412,10 +414,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private static bool TryGetNewLine(ref ReadableBuffer buffer, out ReadCursor found)
|
private static bool TryGetNewLine(ref ReadOnlyBuffer buffer, out Position found)
|
||||||
{
|
{
|
||||||
var start = buffer.Start;
|
var start = buffer.Start;
|
||||||
if (ReadCursorOperations.Seek(start, buffer.End, out found, ByteLF) != -1)
|
if (ReadOnlyBuffer.Seek(start, buffer.End, out found, ByteLF) != -1)
|
||||||
{
|
{
|
||||||
// Move 1 byte past the \n
|
// Move 1 byte past the \n
|
||||||
found = buffer.Move(found, 1);
|
found = buffer.Move(found, 1);
|
||||||
|
|
|
||||||
|
|
@ -380,7 +380,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool BeginRead(out ReadableBufferAwaitable awaitable)
|
protected virtual bool BeginRead(out ValueAwaiter<ReadResult> awaitable)
|
||||||
{
|
{
|
||||||
awaitable = default;
|
awaitable = default;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1302,7 +1302,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
(
|
(
|
||||||
pool: _context.MemoryPool,
|
pool: _context.MemoryPool,
|
||||||
readerScheduler: ServiceContext.ThreadPool,
|
readerScheduler: ServiceContext.ThreadPool,
|
||||||
writerScheduler: InlineScheduler.Default,
|
writerScheduler: Scheduler.Inline,
|
||||||
maximumSizeHigh: 1,
|
maximumSizeHigh: 1,
|
||||||
maximumSizeLow: 1
|
maximumSizeLow: 1
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
// 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.
|
||||||
|
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
public interface IHttpParser<TRequestHandler> where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler
|
public interface IHttpParser<TRequestHandler> where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler
|
||||||
{
|
{
|
||||||
bool ParseRequestLine(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined);
|
bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined);
|
||||||
|
|
||||||
bool ParseHeaders(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes);
|
bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.Buffers;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
private static byte[] _numericBytesScratch;
|
private static byte[] _numericBytesScratch;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Span<byte> ToSpan(this ReadableBuffer buffer)
|
public static ReadOnlySpan<byte> ToSpan(this ReadOnlyBuffer buffer)
|
||||||
{
|
{
|
||||||
if (buffer.IsSingleSpan)
|
if (buffer.IsSingleSpan)
|
||||||
{
|
{
|
||||||
|
|
@ -35,6 +36,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)
|
||||||
|
{
|
||||||
|
if (!MemoryMarshal.TryGetArray(memory, out var result))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Buffer backed by array was expected");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data)
|
public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(data))
|
if (string.IsNullOrEmpty(data))
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// 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.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -214,7 +216,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ParsePreface(ReadableBuffer readableBuffer, out ReadCursor consumed, out ReadCursor examined)
|
private bool ParsePreface(ReadOnlyBuffer readableBuffer, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = readableBuffer.Start;
|
consumed = readableBuffer.Start;
|
||||||
examined = readableBuffer.End;
|
examined = readableBuffer.End;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
// 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.
|
||||||
|
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
|
||||||
{
|
{
|
||||||
public static class Http2FrameReader
|
public static class Http2FrameReader
|
||||||
{
|
{
|
||||||
public static bool ReadFrame(ReadableBuffer readableBuffer, Http2Frame frame, out ReadCursor consumed, out ReadCursor examined)
|
public static bool ReadFrame(ReadOnlyBuffer readableBuffer, Http2Frame frame, out Position consumed, out Position examined)
|
||||||
{
|
{
|
||||||
consumed = readableBuffer.Start;
|
consumed = readableBuffer.Start;
|
||||||
examined = readableBuffer.End;
|
examined = readableBuffer.End;
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
(
|
(
|
||||||
pool: MemoryPool,
|
pool: MemoryPool,
|
||||||
readerScheduler: _context.ServiceContext.ThreadPool,
|
readerScheduler: _context.ServiceContext.ThreadPool,
|
||||||
writerScheduler: InlineScheduler.Default,
|
writerScheduler: Scheduler.Inline,
|
||||||
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
|
||||||
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
|
||||||
);
|
);
|
||||||
|
|
@ -81,8 +81,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
|
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
|
||||||
(
|
(
|
||||||
pool: MemoryPool,
|
pool: MemoryPool,
|
||||||
readerScheduler: InlineScheduler.Default,
|
readerScheduler: Scheduler.Inline,
|
||||||
writerScheduler: InlineScheduler.Default,
|
writerScheduler: Scheduler.Inline,
|
||||||
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
|
||||||
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
{
|
{
|
||||||
public class InlineLoggingThreadPool : IThreadPool
|
public class InlineLoggingThreadPool : KestrelThreadPool
|
||||||
{
|
{
|
||||||
private readonly IKestrelTrace _log;
|
private readonly IKestrelTrace _log;
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
_log = log;
|
_log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(Action action)
|
public override void Run(Action action)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -28,12 +28,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnsafeRun(WaitCallback action, object state)
|
public override void UnsafeRun(WaitCallback action, object state)
|
||||||
{
|
{
|
||||||
action(state);
|
action(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Schedule(Action<object> action, object state)
|
public override void Schedule(Action action)
|
||||||
|
{
|
||||||
|
Run(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Schedule(Action<object> action, object state)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
{
|
{
|
||||||
public interface IThreadPool : IScheduler
|
public abstract class KestrelThreadPool: Scheduler
|
||||||
{
|
{
|
||||||
void Run(Action action);
|
public abstract void Run(Action action);
|
||||||
void UnsafeRun(WaitCallback action, object state);
|
public abstract void UnsafeRun(WaitCallback action, object state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
{
|
{
|
||||||
public class LoggingThreadPool : IThreadPool
|
public class LoggingThreadPool : KestrelThreadPool
|
||||||
{
|
{
|
||||||
private readonly IKestrelTrace _log;
|
private readonly IKestrelTrace _log;
|
||||||
|
|
||||||
|
|
@ -40,17 +40,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(Action action)
|
public override void Run(Action action)
|
||||||
{
|
{
|
||||||
ThreadPool.QueueUserWorkItem(_runAction, action);
|
ThreadPool.QueueUserWorkItem(_runAction, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnsafeRun(WaitCallback action, object state)
|
public override void UnsafeRun(WaitCallback action, object state)
|
||||||
{
|
{
|
||||||
ThreadPool.QueueUserWorkItem(action, state);
|
ThreadPool.QueueUserWorkItem(action, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Schedule(Action<object> action, object state)
|
public override void Schedule(Action action)
|
||||||
|
{
|
||||||
|
Run(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Schedule(Action<object> action, object state)
|
||||||
{
|
{
|
||||||
Run(() => action(state));
|
Run(() => action(state));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
public IKestrelTrace Log { get; set; }
|
public IKestrelTrace Log { get; set; }
|
||||||
|
|
||||||
public IThreadPool ThreadPool { get; set; }
|
public KestrelThreadPool ThreadPool { get; set; }
|
||||||
|
|
||||||
public IHttpParser<Http1ParsingHandler> HttpParser { get; set; }
|
public IHttpParser<Http1ParsingHandler> HttpParser { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
||||||
|
|
||||||
// TODO: This logic will eventually move into the IConnectionHandler<T> and off
|
// TODO: This logic will eventually move into the IConnectionHandler<T> and off
|
||||||
// the service context once we get to https://github.com/aspnet/KestrelHttpServer/issues/1662
|
// the service context once we get to https://github.com/aspnet/KestrelHttpServer/issues/1662
|
||||||
IThreadPool threadPool = null;
|
KestrelThreadPool threadPool = null;
|
||||||
switch (serverOptions.ApplicationSchedulingMode)
|
switch (serverOptions.ApplicationSchedulingMode)
|
||||||
{
|
{
|
||||||
case SchedulingMode.Default:
|
case SchedulingMode.Default:
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
|
|
||||||
public virtual MemoryPool MemoryPool { get; }
|
public virtual MemoryPool MemoryPool { get; }
|
||||||
public virtual IScheduler InputWriterScheduler { get; }
|
public virtual Scheduler InputWriterScheduler { get; }
|
||||||
public virtual IScheduler OutputReaderScheduler { get; }
|
public virtual Scheduler OutputReaderScheduler { get; }
|
||||||
|
|
||||||
public IPipeConnection Transport { get; set; }
|
public IPipeConnection Transport { get; set; }
|
||||||
public IPipeConnection Application { get; set; }
|
public IPipeConnection Application { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Buffers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Protocols;
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
@ -183,7 +184,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
_bufferHandle.Dispose();
|
_bufferHandle.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ApplyBackpressureAsync(WritableBufferAwaitable flushTask)
|
private async Task ApplyBackpressureAsync(ValueAwaiter<FlushResult> flushTask)
|
||||||
{
|
{
|
||||||
Log.ConnectionPause(ConnectionId);
|
Log.ConnectionPause(ConnectionId);
|
||||||
_socket.ReadStop();
|
_socket.ReadStop();
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
public ListenerContext ListenerContext { get; set; }
|
public ListenerContext ListenerContext { get; set; }
|
||||||
|
|
||||||
public override MemoryPool MemoryPool => ListenerContext.Thread.MemoryPool;
|
public override MemoryPool MemoryPool => ListenerContext.Thread.MemoryPool;
|
||||||
public override IScheduler InputWriterScheduler => ListenerContext.Thread;
|
public override Scheduler InputWriterScheduler => ListenerContext.Thread;
|
||||||
public override IScheduler OutputReaderScheduler => ListenerContext.Thread;
|
public override Scheduler OutputReaderScheduler => ListenerContext.Thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
public class LibuvThread : IScheduler
|
public class LibuvThread : Scheduler
|
||||||
{
|
{
|
||||||
// maximum times the work queues swapped and are processed in a single pass
|
// maximum times the work queues swapped and are processed in a single pass
|
||||||
// as completing a task may immediately have write data to put on the network
|
// as completing a task may immediately have write data to put on the network
|
||||||
|
|
@ -390,7 +390,12 @@ 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 void Schedule(Action<object> action, object state)
|
public override void Schedule(Action action)
|
||||||
|
{
|
||||||
|
Post(state => state(), action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Schedule(Action<object> action, object state)
|
||||||
{
|
{
|
||||||
Post(action, state);
|
Post(action, state);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
||||||
_bufs = handle + requestSize;
|
_bufs = handle + requestSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadableBuffer buffer)
|
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadOnlyBuffer buffer)
|
||||||
{
|
{
|
||||||
Write(handle, buffer, LibuvAwaitable<UvWriteReq>.Callback, _awaitable);
|
Write(handle, buffer, LibuvAwaitable<UvWriteReq>.Callback, _awaitable);
|
||||||
return _awaitable;
|
return _awaitable;
|
||||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
|
||||||
|
|
||||||
private unsafe void Write(
|
private unsafe void Write(
|
||||||
UvStreamHandle handle,
|
UvStreamHandle handle,
|
||||||
ReadableBuffer buffer,
|
ReadOnlyBuffer buffer,
|
||||||
Action<UvWriteReq, int, UvException, object> callback,
|
Action<UvWriteReq, int, UvException, object> callback,
|
||||||
object state)
|
object state)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,24 @@
|
||||||
// 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.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
{
|
{
|
||||||
public static class BufferExtensions
|
public static class BufferExtensions
|
||||||
{
|
{
|
||||||
public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
|
public static ArraySegment<byte> GetArray(this Memory<byte> memory)
|
||||||
{
|
{
|
||||||
ArraySegment<byte> result;
|
if (!memory.TryGetArray(out var result))
|
||||||
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)
|
||||||
|
{
|
||||||
|
if (!MemoryMarshal.TryGetArray(memory, out var result))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Buffer backed by array was expected");
|
throw new InvalidOperationException("Buffer backed by array was expected");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MemoryPool MemoryPool { get; }
|
public override MemoryPool MemoryPool { get; }
|
||||||
public override IScheduler InputWriterScheduler => InlineScheduler.Default;
|
public override Scheduler InputWriterScheduler => Scheduler.Inline;
|
||||||
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
public override Scheduler OutputReaderScheduler => Scheduler.TaskRun;
|
||||||
|
|
||||||
public async Task StartAsync(IConnectionHandler connectionHandler)
|
public async Task StartAsync(IConnectionHandler connectionHandler)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
// 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.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -24,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
_eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError);
|
_eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SocketAwaitable SendAsync(ReadableBuffer buffers)
|
public SocketAwaitable SendAsync(ReadOnlyBuffer buffers)
|
||||||
{
|
{
|
||||||
if (buffers.IsSingleSpan)
|
if (buffers.IsSingleSpan)
|
||||||
{
|
{
|
||||||
|
|
@ -50,7 +52,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
return _awaitable;
|
return _awaitable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketAwaitable SendAsync(Memory<byte> buffer)
|
private SocketAwaitable SendAsync(ReadOnlyMemory<byte> memory)
|
||||||
{
|
{
|
||||||
// The BufferList getter is much less expensive then the setter.
|
// The BufferList getter is much less expensive then the setter.
|
||||||
if (_eventArgs.BufferList != null)
|
if (_eventArgs.BufferList != null)
|
||||||
|
|
@ -59,9 +61,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP2_1
|
#if NETCOREAPP2_1
|
||||||
_eventArgs.SetBuffer(buffer);
|
_eventArgs.SetBuffer(MemoryMarshal.AsMemory(memory));
|
||||||
#else
|
#else
|
||||||
var segment = buffer.GetArray();
|
var segment = memory.GetArray();
|
||||||
|
|
||||||
_eventArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);
|
_eventArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -73,7 +75,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
return _awaitable;
|
return _awaitable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ArraySegment<byte>> GetBufferList(ReadableBuffer buffer)
|
private List<ArraySegment<byte>> GetBufferList(ReadOnlyBuffer buffer)
|
||||||
{
|
{
|
||||||
Debug.Assert(!buffer.IsEmpty);
|
Debug.Assert(!buffer.IsEmpty);
|
||||||
Debug.Assert(!buffer.IsSingleSpan);
|
Debug.Assert(!buffer.IsSingleSpan);
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ namespace Microsoft.AspNetCore.Protocols.Features
|
||||||
|
|
||||||
IPipeConnection Application { get; set; }
|
IPipeConnection Application { get; set; }
|
||||||
|
|
||||||
IScheduler InputWriterScheduler { get; }
|
Scheduler InputWriterScheduler { get; }
|
||||||
|
|
||||||
IScheduler OutputReaderScheduler { get; }
|
Scheduler OutputReaderScheduler { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
public IPipeConnection Transport { get; set; }
|
public IPipeConnection Transport { get; set; }
|
||||||
public IPipeConnection Application { get; set; }
|
public IPipeConnection Application { get; set; }
|
||||||
|
|
||||||
public IScheduler InputWriterScheduler => TaskRunScheduler.Default;
|
public Scheduler InputWriterScheduler => Scheduler.TaskRun;
|
||||||
|
|
||||||
public IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
public Scheduler OutputReaderScheduler => Scheduler.TaskRun;
|
||||||
|
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Sequences;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -33,8 +34,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
private readonly ServiceContext _serviceContext;
|
private readonly ServiceContext _serviceContext;
|
||||||
private readonly Http1ConnectionContext _http1ConnectionContext;
|
private readonly Http1ConnectionContext _http1ConnectionContext;
|
||||||
private readonly MemoryPool _pipelineFactory;
|
private readonly MemoryPool _pipelineFactory;
|
||||||
private ReadCursor _consumed;
|
private Position _consumed;
|
||||||
private ReadCursor _examined;
|
private Position _examined;
|
||||||
private Mock<ITimeoutControl> _timeoutControl;
|
private Mock<ITimeoutControl> _timeoutControl;
|
||||||
|
|
||||||
public Http1ConnectionTests()
|
public Http1ConnectionTests()
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
// 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.Buffers;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.IO.Pipelines.Testing;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
string expectedVersion)
|
string expectedVersion)
|
||||||
{
|
{
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine)
|
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine)
|
||||||
{
|
{
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||||
|
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine)
|
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine)
|
||||||
{
|
{
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
var parser = CreateParser(mockTrace.Object);
|
var parser = CreateParser(mockTrace.Object);
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
var parser = CreateParser(mockTrace.Object);
|
var parser = CreateParser(mockTrace.Object);
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
|
|
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
var parser = CreateParser(mockTrace.Object);
|
var parser = CreateParser(mockTrace.Object);
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
|
|
@ -179,7 +179,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
|
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
Assert.False(parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
Assert.False(parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +204,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
|
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||||
|
|
||||||
|
|
@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
|
|
||||||
const string headerLine = "Header: value\r\n\r";
|
const string headerLine = "Header: value\r\n\r";
|
||||||
var buffer1 = ReadableBuffer.Create(Encoding.ASCII.GetBytes(headerLine));
|
var buffer1 = new ReadOnlyBuffer(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));
|
||||||
|
|
||||||
|
|
@ -302,7 +302,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
Assert.Equal(buffer1.End, examined);
|
Assert.Equal(buffer1.End, examined);
|
||||||
Assert.Equal(headerLine.Length - 1, consumedBytes);
|
Assert.Equal(headerLine.Length - 1, consumedBytes);
|
||||||
|
|
||||||
var buffer2 = ReadableBuffer.Create(Encoding.ASCII.GetBytes("\r\n"));
|
var buffer2 = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("\r\n"));
|
||||||
Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes));
|
Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes));
|
||||||
|
|
||||||
Assert.Equal(buffer2.End, consumed);
|
Assert.Equal(buffer2.End, consumed);
|
||||||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
var parser = CreateParser(mockTrace.Object);
|
var parser = CreateParser(mockTrace.Object);
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
|
|
@ -341,7 +341,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
var parser = CreateParser(mockTrace.Object);
|
var parser = CreateParser(mockTrace.Object);
|
||||||
|
|
||||||
// Invalid request line
|
// Invalid request line
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
|
|
||||||
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
var exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
|
|
@ -351,7 +351,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode);
|
Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode);
|
||||||
|
|
||||||
// Unrecognized HTTP version
|
// Unrecognized HTTP version
|
||||||
buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
|
buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
|
||||||
|
|
||||||
exception = Assert.Throws<BadHttpRequestException>(() =>
|
exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
|
||||||
|
|
@ -360,7 +360,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode);
|
Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode);
|
||||||
|
|
||||||
// Invalid request header
|
// Invalid request header
|
||||||
buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("Header: value\n\r\n"));
|
buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("Header: value\n\r\n"));
|
||||||
|
|
||||||
exception = Assert.Throws<BadHttpRequestException>(() =>
|
exception = Assert.Throws<BadHttpRequestException>(() =>
|
||||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
|
||||||
|
|
@ -369,27 +369,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
|
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ParseRequestLineSplitBufferWithoutNewLineDoesNotUpdateConsumed()
|
|
||||||
{
|
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
|
||||||
var buffer = BufferUtilities.CreateBuffer("GET ", "/");
|
|
||||||
|
|
||||||
var requestHandler = new RequestHandler();
|
|
||||||
var result = parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined);
|
|
||||||
|
|
||||||
Assert.False(result);
|
|
||||||
Assert.Equal(buffer.Start, consumed);
|
|
||||||
Assert.Equal(buffer.End, examined);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void VerifyHeader(
|
private void VerifyHeader(
|
||||||
string headerName,
|
string headerName,
|
||||||
string rawHeaderValue,
|
string rawHeaderValue,
|
||||||
string expectedHeaderValue)
|
string expectedHeaderValue)
|
||||||
{
|
{
|
||||||
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
var parser = CreateParser(Mock.Of<IKestrelTrace>());
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
|
||||||
|
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||||
|
|
@ -407,7 +393,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(Mock.Of<IKestrelTrace>());
|
||||||
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders));
|
var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
|
||||||
|
|
||||||
var requestHandler = new RequestHandler();
|
var requestHandler = new RequestHandler();
|
||||||
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
var pipeOptions = new PipeOptions
|
var pipeOptions = new PipeOptions
|
||||||
(
|
(
|
||||||
pool: _memoryPool,
|
pool: _memoryPool,
|
||||||
readerScheduler: Mock.Of<IScheduler>()
|
readerScheduler: Mock.Of<Scheduler>()
|
||||||
);
|
);
|
||||||
|
|
||||||
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize;
|
serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize;
|
||||||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||||
|
|
||||||
var mockScheduler = Mock.Of<IScheduler>();
|
var mockScheduler = Mock.Of<Scheduler>();
|
||||||
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
|
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
|
||||||
|
|
||||||
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow);
|
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow);
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
|
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
|
||||||
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
serviceContext.ThreadPool = new LoggingThreadPool(null);
|
||||||
|
|
||||||
var mockScheduler = Mock.Of<IScheduler>();
|
var mockScheduler = Mock.Of<Scheduler>();
|
||||||
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
|
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
|
||||||
|
|
||||||
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow);
|
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow);
|
||||||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeLow);
|
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeLow);
|
||||||
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeHigh);
|
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeHigh);
|
||||||
Assert.Same(serviceContext.ThreadPool, connectionLifetime.AdaptedInputPipeOptions.ReaderScheduler);
|
Assert.Same(serviceContext.ThreadPool, connectionLifetime.AdaptedInputPipeOptions.ReaderScheduler);
|
||||||
Assert.Same(InlineScheduler.Default, connectionLifetime.AdaptedInputPipeOptions.WriterScheduler);
|
Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedInputPipeOptions.WriterScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -87,8 +87,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
|
|
||||||
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeLow);
|
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeLow);
|
||||||
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeHigh);
|
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeHigh);
|
||||||
Assert.Same(InlineScheduler.Default, connectionLifetime.AdaptedOutputPipeOptions.ReaderScheduler);
|
Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.ReaderScheduler);
|
||||||
Assert.Same(InlineScheduler.Default, connectionLifetime.AdaptedOutputPipeOptions.WriterScheduler);
|
Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.WriterScheduler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,11 +117,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
|
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
|
||||||
var transport = new LibuvTransport(mockLibuv, transportContext, null);
|
var transport = new LibuvTransport(mockLibuv, transportContext, null);
|
||||||
var thread = new LibuvThread(transport);
|
var thread = new LibuvThread(transport);
|
||||||
var mockScheduler = new Mock<IScheduler>();
|
var mockScheduler = new Mock<Scheduler>();
|
||||||
Action backPressure = null;
|
Action backPressure = null;
|
||||||
mockScheduler.Setup(m => m.Schedule(It.IsAny<Action<object>>(), It.IsAny<object>())).Callback<Action<object>, object>((a, o) =>
|
mockScheduler.Setup(m => m.Schedule(It.IsAny<Action>())).Callback<Action>(a =>
|
||||||
{
|
{
|
||||||
backPressure = () => a(o);
|
backPressure = a;
|
||||||
});
|
});
|
||||||
mockConnectionHandler.InputOptions = pool =>
|
mockConnectionHandler.InputOptions = pool =>
|
||||||
new PipeOptions(
|
new PipeOptions(
|
||||||
|
|
|
||||||
|
|
@ -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.Buffers;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
@ -68,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
|
|
||||||
await writeRequest.WriteAsync(
|
await writeRequest.WriteAsync(
|
||||||
serverConnectionPipe,
|
serverConnectionPipe,
|
||||||
ReadableBuffer.Create(new byte[] { 1, 2, 3, 4 }));
|
new ReadOnlyBuffer(new byte[] { 1, 2, 3, 4 }));
|
||||||
|
|
||||||
writeRequest.Dispose();
|
writeRequest.Dispose();
|
||||||
serverConnectionPipe.Dispose();
|
serverConnectionPipe.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -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.Buffers;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
@ -161,7 +162,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
var req = new UvWriteReq(_logger);
|
var req = new UvWriteReq(_logger);
|
||||||
req.DangerousInit(loop);
|
req.DangerousInit(loop);
|
||||||
var block = ReadableBuffer.Create(new byte[] { 65, 66, 67, 68, 69 });
|
var block = new ReadOnlyBuffer(new byte[] { 65, 66, 67, 68, 69 });
|
||||||
|
|
||||||
await req.WriteAsync(
|
await req.WriteAsync(
|
||||||
tcp2,
|
tcp2,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue