Initial bedrock refactoring (#1995)
- Added Protocols.Abstractions - IConnectionHandler.OnConnection takes an IFeatureCollection instead of IConnectionInfo - Removed IConnectionContext and IConnectionInformation replaced with IConnectionTransportFeature - Updated FrameConnectionContext and FrameContext to have the relevant state instead of flowing the ConnectionInformation. - Updated tests
This commit is contained in:
parent
f3745608af
commit
5c775073a4
|
|
@ -1,6 +1,6 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26706.0
|
VisualStudioVersion = 15.0.26730.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
|
@ -80,6 +80,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Libuv.Tes
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Tests", "test\Kestrel.Tests\Kestrel.Tests.csproj", "{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Tests", "test\Kestrel.Tests\Kestrel.Tests.csproj", "{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protocols.Abstractions", "src\Protocols.Abstractions\Protocols.Abstractions.csproj", "{6956CF5C-3163-4398-8628-4ECA569245B5}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -258,6 +260,18 @@ Global
|
||||||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x64.Build.0 = Release|Any CPU
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x86.ActiveCfg = Release|Any CPU
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x86.Build.0 = Release|Any CPU
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -279,6 +293,7 @@ Global
|
||||||
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||||
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||||
|
{6956CF5C-3163-4398-8628-4ECA569245B5} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
|
SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
|
|
|
||||||
|
|
@ -2,8 +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.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
||||||
|
|
@ -24,38 +28,73 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
_application = application;
|
_application = application;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConnectionContext OnConnection(IConnectionInformation connectionInfo)
|
public void OnConnection(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
var inputPipe = connectionInfo.PipeFactory.Create(GetInputPipeOptions(connectionInfo.InputWriterScheduler));
|
var connectionContext = new DefaultConnectionContext(features);
|
||||||
var outputPipe = connectionInfo.PipeFactory.Create(GetOutputPipeOptions(connectionInfo.OutputReaderScheduler));
|
|
||||||
|
var transportFeature = connectionContext.Features.Get<IConnectionTransportFeature>();
|
||||||
|
|
||||||
|
var inputPipe = transportFeature.PipeFactory.Create(GetInputPipeOptions(transportFeature.InputWriterScheduler));
|
||||||
|
var outputPipe = transportFeature.PipeFactory.Create(GetOutputPipeOptions(transportFeature.OutputReaderScheduler));
|
||||||
|
|
||||||
var connectionId = CorrelationIdGenerator.GetNextId();
|
var connectionId = CorrelationIdGenerator.GetNextId();
|
||||||
var frameConnectionId = Interlocked.Increment(ref _lastFrameConnectionId);
|
var frameConnectionId = Interlocked.Increment(ref _lastFrameConnectionId);
|
||||||
|
|
||||||
|
// Set the transport and connection id
|
||||||
|
connectionContext.ConnectionId = connectionId;
|
||||||
|
transportFeature.Connection = new PipeConnection(inputPipe.Reader, outputPipe.Writer);
|
||||||
|
var applicationConnection = new PipeConnection(outputPipe.Reader, inputPipe.Writer);
|
||||||
|
|
||||||
if (!_serviceContext.ConnectionManager.NormalConnectionCount.TryLockOne())
|
if (!_serviceContext.ConnectionManager.NormalConnectionCount.TryLockOne())
|
||||||
{
|
{
|
||||||
var goAway = new RejectionConnection(inputPipe, outputPipe, connectionId, _serviceContext);
|
var goAway = new RejectionConnection(inputPipe, outputPipe, connectionId, _serviceContext)
|
||||||
|
{
|
||||||
|
Connection = applicationConnection
|
||||||
|
};
|
||||||
|
|
||||||
|
connectionContext.Features.Set<IConnectionApplicationFeature>(goAway);
|
||||||
|
|
||||||
goAway.Reject();
|
goAway.Reject();
|
||||||
return goAway;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var connection = new FrameConnection(new FrameConnectionContext
|
var frameConnectionContext = new FrameConnectionContext
|
||||||
{
|
{
|
||||||
ConnectionId = connectionId,
|
ConnectionId = connectionId,
|
||||||
FrameConnectionId = frameConnectionId,
|
FrameConnectionId = frameConnectionId,
|
||||||
ServiceContext = _serviceContext,
|
ServiceContext = _serviceContext,
|
||||||
ConnectionInformation = connectionInfo,
|
PipeFactory = connectionContext.PipeFactory,
|
||||||
ConnectionAdapters = _listenOptions.ConnectionAdapters,
|
ConnectionAdapters = _listenOptions.ConnectionAdapters,
|
||||||
Input = inputPipe,
|
Input = inputPipe,
|
||||||
Output = outputPipe,
|
Output = outputPipe
|
||||||
});
|
};
|
||||||
|
|
||||||
|
var connectionFeature = connectionContext.Features.Get<IHttpConnectionFeature>();
|
||||||
|
|
||||||
|
if (connectionFeature != null)
|
||||||
|
{
|
||||||
|
if (connectionFeature.LocalIpAddress != null)
|
||||||
|
{
|
||||||
|
frameConnectionContext.LocalEndPoint = new IPEndPoint(connectionFeature.LocalIpAddress, connectionFeature.LocalPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionFeature.RemoteIpAddress != null)
|
||||||
|
{
|
||||||
|
frameConnectionContext.RemoteEndPoint = new IPEndPoint(connectionFeature.RemoteIpAddress, connectionFeature.RemotePort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var connection = new FrameConnection(frameConnectionContext)
|
||||||
|
{
|
||||||
|
Connection = applicationConnection
|
||||||
|
};
|
||||||
|
|
||||||
|
connectionContext.Features.Set<IConnectionApplicationFeature>(connection);
|
||||||
|
|
||||||
// Since data cannot be added to the inputPipe by the transport until OnConnection returns,
|
// Since data cannot be added to the inputPipe by the transport until OnConnection returns,
|
||||||
// Frame.ProcessRequestsAsync is guaranteed to unblock the transport thread before calling
|
// Frame.ProcessRequestsAsync is guaranteed to unblock the transport thread before calling
|
||||||
// application code.
|
// application code.
|
||||||
connection.StartRequestProcessing<TContext>(_application);
|
connection.StartRequestProcessing(_application);
|
||||||
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,20 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
public class FrameConnection : IConnectionContext, ITimeoutControl
|
public class FrameConnection : IConnectionApplicationFeature, ITimeoutControl
|
||||||
{
|
{
|
||||||
private readonly FrameConnectionContext _context;
|
private readonly FrameConnectionContext _context;
|
||||||
private List<IAdaptedConnection> _adaptedConnections;
|
private List<IAdaptedConnection> _adaptedConnections;
|
||||||
|
|
@ -55,8 +56,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
public string ConnectionId => _context.ConnectionId;
|
public string ConnectionId => _context.ConnectionId;
|
||||||
public IPipeWriter Input => _context.Input.Writer;
|
public IPipeWriter Input => _context.Input.Writer;
|
||||||
public IPipeReader Output => _context.Output.Reader;
|
public IPipeReader Output => _context.Output.Reader;
|
||||||
|
public IPEndPoint LocalEndPoint => _context.LocalEndPoint;
|
||||||
|
public IPEndPoint RemoteEndPoint => _context.RemoteEndPoint;
|
||||||
|
|
||||||
private PipeFactory PipeFactory => _context.ConnectionInformation.PipeFactory;
|
private PipeFactory PipeFactory => _context.PipeFactory;
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
|
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
|
||||||
|
|
@ -77,6 +80,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
|
|
||||||
private IKestrelTrace Log => _context.ServiceContext.Log;
|
private IKestrelTrace Log => _context.ServiceContext.Log;
|
||||||
|
|
||||||
|
public IPipeConnection Connection { get; set; }
|
||||||
|
|
||||||
public void StartRequestProcessing<TContext>(IHttpApplication<TContext> application)
|
public void StartRequestProcessing<TContext>(IHttpApplication<TContext> application)
|
||||||
{
|
{
|
||||||
_lifetimeTask = ProcessRequestsAsync(application);
|
_lifetimeTask = ProcessRequestsAsync(application);
|
||||||
|
|
@ -89,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log.ConnectionStart(ConnectionId);
|
Log.ConnectionStart(ConnectionId);
|
||||||
KestrelEventSource.Log.ConnectionStart(this, _context.ConnectionInformation);
|
KestrelEventSource.Log.ConnectionStart(this);
|
||||||
|
|
||||||
AdaptedPipeline adaptedPipeline = null;
|
AdaptedPipeline adaptedPipeline = null;
|
||||||
var adaptedPipelineTask = Task.CompletedTask;
|
var adaptedPipelineTask = Task.CompletedTask;
|
||||||
|
|
@ -156,7 +161,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
_frame = new Frame<TContext>(application, new FrameContext
|
_frame = new Frame<TContext>(application, new FrameContext
|
||||||
{
|
{
|
||||||
ConnectionId = _context.ConnectionId,
|
ConnectionId = _context.ConnectionId,
|
||||||
ConnectionInformation = _context.ConnectionInformation,
|
PipeFactory = PipeFactory,
|
||||||
|
LocalEndPoint = LocalEndPoint,
|
||||||
|
RemoteEndPoint = RemoteEndPoint,
|
||||||
ServiceContext = _context.ServiceContext,
|
ServiceContext = _context.ServiceContext,
|
||||||
TimeoutControl = this,
|
TimeoutControl = this,
|
||||||
Input = input,
|
Input = input,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -14,7 +14,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
public long FrameConnectionId { get; set; }
|
public long FrameConnectionId { get; set; }
|
||||||
public ServiceContext ServiceContext { get; set; }
|
public ServiceContext ServiceContext { get; set; }
|
||||||
public List<IConnectionAdapter> ConnectionAdapters { get; set; }
|
public List<IConnectionAdapter> ConnectionAdapters { get; set; }
|
||||||
public IConnectionInformation ConnectionInformation { get; set; }
|
public PipeFactory PipeFactory { get; set; }
|
||||||
|
public IPEndPoint LocalEndPoint { get; set; }
|
||||||
|
public IPEndPoint RemoteEndPoint { get; set; }
|
||||||
|
|
||||||
public IPipe Input { get; set; }
|
public IPipe Input { get; set; }
|
||||||
public IPipe Output { get; set; }
|
public IPipe Output { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
|
|
@ -103,7 +103,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
public IPipe RequestBodyPipe { get; }
|
public IPipe RequestBodyPipe { get; }
|
||||||
|
|
||||||
public ServiceContext ServiceContext => _frameContext.ServiceContext;
|
public ServiceContext ServiceContext => _frameContext.ServiceContext;
|
||||||
public IConnectionInformation ConnectionInformation => _frameContext.ConnectionInformation;
|
private IPEndPoint LocalEndPoint => _frameContext.LocalEndPoint;
|
||||||
|
private IPEndPoint RemoteEndPoint => _frameContext.RemoteEndPoint;
|
||||||
|
|
||||||
public IFeatureCollection ConnectionFeatures { get; set; }
|
public IFeatureCollection ConnectionFeatures { get; set; }
|
||||||
public IPipeReader Input => _frameContext.Input;
|
public IPipeReader Input => _frameContext.Input;
|
||||||
|
|
@ -114,8 +115,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
private DateHeaderValueManager DateHeaderValueManager => ServiceContext.DateHeaderValueManager;
|
private DateHeaderValueManager DateHeaderValueManager => ServiceContext.DateHeaderValueManager;
|
||||||
// Hold direct reference to ServerOptions since this is used very often in the request processing path
|
// Hold direct reference to ServerOptions since this is used very often in the request processing path
|
||||||
private KestrelServerOptions ServerOptions { get; }
|
private KestrelServerOptions ServerOptions { get; }
|
||||||
private IPEndPoint LocalEndPoint => ConnectionInformation.LocalEndPoint;
|
|
||||||
private IPEndPoint RemoteEndPoint => ConnectionInformation.RemoteEndPoint;
|
|
||||||
protected string ConnectionId => _frameContext.ConnectionId;
|
protected string ConnectionId => _frameContext.ConnectionId;
|
||||||
|
|
||||||
public string ConnectionIdFeature { get; set; }
|
public string ConnectionIdFeature { get; set; }
|
||||||
|
|
@ -1376,7 +1375,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
}
|
}
|
||||||
|
|
||||||
private IPipe CreateRequestBodyPipe()
|
private IPipe CreateRequestBodyPipe()
|
||||||
=> ConnectionInformation.PipeFactory.Create(new PipeOptions
|
=> _frameContext.PipeFactory.Create(new PipeOptions
|
||||||
{
|
{
|
||||||
ReaderScheduler = ServiceContext.ThreadPool,
|
ReaderScheduler = ServiceContext.ThreadPool,
|
||||||
WriterScheduler = InlineScheduler.Default,
|
WriterScheduler = InlineScheduler.Default,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
// 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.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Net;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +12,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
public ServiceContext ServiceContext { get; set; }
|
public ServiceContext ServiceContext { get; set; }
|
||||||
public IConnectionInformation ConnectionInformation { get; set; }
|
public PipeFactory PipeFactory { get; set; }
|
||||||
|
public IPEndPoint RemoteEndPoint { get; set; }
|
||||||
|
public IPEndPoint LocalEndPoint { get; set; }
|
||||||
public ITimeoutControl TimeoutControl { get; set; }
|
public ITimeoutControl TimeoutControl { get; set; }
|
||||||
public IPipeReader Input { get; set; }
|
public IPipeReader Input { get; set; }
|
||||||
public IPipe Output { get; set; }
|
public IPipe Output { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
// 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.Diagnostics.Tracing;
|
using System.Diagnostics.Tracing;
|
||||||
|
using System.Net;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
||||||
|
|
@ -26,15 +29,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
// - Avoid renaming methods or parameters marked with EventAttribute. EventSource uses these to form the event object.
|
// - Avoid renaming methods or parameters marked with EventAttribute. EventSource uses these to form the event object.
|
||||||
|
|
||||||
[NonEvent]
|
[NonEvent]
|
||||||
public void ConnectionStart(IConnectionContext context, IConnectionInformation information)
|
public void ConnectionStart(FrameConnection connection)
|
||||||
{
|
{
|
||||||
// avoid allocating strings unless this event source is enabled
|
// avoid allocating strings unless this event source is enabled
|
||||||
if (IsEnabled())
|
if (IsEnabled())
|
||||||
{
|
{
|
||||||
ConnectionStart(
|
ConnectionStart(
|
||||||
context.ConnectionId,
|
connection.ConnectionId,
|
||||||
information.LocalEndPoint.ToString(),
|
connection.LocalEndPoint.ToString(),
|
||||||
information.RemoteEndPoint.ToString());
|
connection.RemoteEndPoint.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
}
|
}
|
||||||
|
|
||||||
[NonEvent]
|
[NonEvent]
|
||||||
public void ConnectionStop(IConnectionContext connection)
|
public void ConnectionStop(FrameConnection connection)
|
||||||
{
|
{
|
||||||
if (IsEnabled())
|
if (IsEnabled())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
public class RejectionConnection : IConnectionContext
|
public class RejectionConnection : IConnectionApplicationFeature
|
||||||
{
|
{
|
||||||
private readonly IKestrelTrace _log;
|
private readonly IKestrelTrace _log;
|
||||||
private readonly IPipe _input;
|
private readonly IPipe _input;
|
||||||
|
|
@ -26,6 +26,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
public IPipeWriter Input => _input.Writer;
|
public IPipeWriter Input => _input.Writer;
|
||||||
public IPipeReader Output => _output.Reader;
|
public IPipeReader Output => _output.Reader;
|
||||||
|
|
||||||
|
public IPipeConnection Connection { get; set; }
|
||||||
|
|
||||||
public void Reject()
|
public void Reject()
|
||||||
{
|
{
|
||||||
KestrelEventSource.Log.ConnectionRejected(ConnectionId);
|
KestrelEventSource.Log.ConnectionRejected(ConnectionId);
|
||||||
|
|
@ -34,12 +36,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
_output.Writer.Complete();
|
_output.Writer.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove these (https://github.com/aspnet/KestrelHttpServer/issues/1772)
|
void IConnectionApplicationFeature.OnConnectionClosed(Exception ex)
|
||||||
void IConnectionContext.OnConnectionClosed(Exception ex)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void IConnectionContext.Abort(Exception ex)
|
void IConnectionApplicationFeature.Abort(Exception ex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO.Pipelines;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|
||||||
{
|
|
||||||
public interface IConnectionContext
|
|
||||||
{
|
|
||||||
string ConnectionId { get; }
|
|
||||||
IPipeWriter Input { get; }
|
|
||||||
IPipeReader Output { get; }
|
|
||||||
|
|
||||||
// TODO: Remove these (https://github.com/aspnet/KestrelHttpServer/issues/1772)
|
|
||||||
void OnConnectionClosed(Exception ex);
|
|
||||||
void Abort(Exception ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
// 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 Microsoft.AspNetCore.Http.Features;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
||||||
{
|
{
|
||||||
public interface IConnectionHandler
|
public interface IConnectionHandler
|
||||||
{
|
{
|
||||||
IConnectionContext OnConnection(IConnectionInformation connectionInfo);
|
void OnConnection(IFeatureCollection features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
// 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.IO.Pipelines;
|
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
|
||||||
{
|
|
||||||
public interface IConnectionInformation
|
|
||||||
{
|
|
||||||
IPEndPoint RemoteEndPoint { get; }
|
|
||||||
IPEndPoint LocalEndPoint { get; }
|
|
||||||
|
|
||||||
PipeFactory PipeFactory { get; }
|
|
||||||
|
|
||||||
IScheduler InputWriterScheduler { get; }
|
|
||||||
IScheduler OutputReaderScheduler { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
||||||
|
{
|
||||||
|
public partial class TransportConnection : IFeatureCollection,
|
||||||
|
IHttpConnectionFeature,
|
||||||
|
IConnectionIdFeature,
|
||||||
|
IConnectionTransportFeature
|
||||||
|
{
|
||||||
|
private static readonly Type IHttpConnectionFeatureType = typeof(IHttpConnectionFeature);
|
||||||
|
private static readonly Type IConnectionIdFeatureType = typeof(IConnectionIdFeature);
|
||||||
|
private static readonly Type IConnectionTransportFeatureType = typeof(IConnectionTransportFeature);
|
||||||
|
private static readonly Type IConnectionApplicationFeatureType = typeof(IConnectionApplicationFeature);
|
||||||
|
|
||||||
|
private object _currentIHttpConnectionFeature;
|
||||||
|
private object _currentIConnectionIdFeature;
|
||||||
|
private object _currentIConnectionTransportFeature;
|
||||||
|
private object _currentIConnectionApplicationFeature;
|
||||||
|
|
||||||
|
private int _featureRevision;
|
||||||
|
|
||||||
|
private List<KeyValuePair<Type, object>> MaybeExtra;
|
||||||
|
|
||||||
|
private object ExtraFeatureGet(Type key)
|
||||||
|
{
|
||||||
|
if (MaybeExtra == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < MaybeExtra.Count; i++)
|
||||||
|
{
|
||||||
|
var kv = MaybeExtra[i];
|
||||||
|
if (kv.Key == key)
|
||||||
|
{
|
||||||
|
return kv.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtraFeatureSet(Type key, object value)
|
||||||
|
{
|
||||||
|
if (MaybeExtra == null)
|
||||||
|
{
|
||||||
|
MaybeExtra = new List<KeyValuePair<Type, object>>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < MaybeExtra.Count; i++)
|
||||||
|
{
|
||||||
|
if (MaybeExtra[i].Key == key)
|
||||||
|
{
|
||||||
|
MaybeExtra[i] = new KeyValuePair<Type, object>(key, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MaybeExtra.Add(new KeyValuePair<Type, object>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IFeatureCollection.IsReadOnly => false;
|
||||||
|
|
||||||
|
int IFeatureCollection.Revision => _featureRevision;
|
||||||
|
|
||||||
|
string IHttpConnectionFeature.ConnectionId
|
||||||
|
{
|
||||||
|
get => ConnectionId;
|
||||||
|
set => ConnectionId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress IHttpConnectionFeature.RemoteIpAddress
|
||||||
|
{
|
||||||
|
get => RemoteAddress;
|
||||||
|
set => RemoteAddress = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress IHttpConnectionFeature.LocalIpAddress
|
||||||
|
{
|
||||||
|
get => LocalAddress;
|
||||||
|
set => LocalAddress = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IHttpConnectionFeature.RemotePort
|
||||||
|
{
|
||||||
|
get => RemotePort;
|
||||||
|
set => RemotePort = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IHttpConnectionFeature.LocalPort
|
||||||
|
{
|
||||||
|
get => LocalPort;
|
||||||
|
set => LocalPort = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PipeFactory IConnectionTransportFeature.PipeFactory => PipeFactory;
|
||||||
|
|
||||||
|
IPipeConnection IConnectionTransportFeature.Connection
|
||||||
|
{
|
||||||
|
get => Transport;
|
||||||
|
set => Transport = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
object IFeatureCollection.this[Type key]
|
||||||
|
{
|
||||||
|
get => FastFeatureGet(key);
|
||||||
|
set => FastFeatureSet(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TFeature IFeatureCollection.Get<TFeature>()
|
||||||
|
{
|
||||||
|
return (TFeature)FastFeatureGet(typeof(TFeature));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IFeatureCollection.Set<TFeature>(TFeature instance)
|
||||||
|
{
|
||||||
|
FastFeatureSet(typeof(TFeature), instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator<KeyValuePair<Type, object>> IEnumerable<KeyValuePair<Type, object>>.GetEnumerator() => FastEnumerable().GetEnumerator();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => FastEnumerable().GetEnumerator();
|
||||||
|
|
||||||
|
private object FastFeatureGet(Type key)
|
||||||
|
{
|
||||||
|
if (key == IHttpConnectionFeatureType)
|
||||||
|
{
|
||||||
|
return _currentIHttpConnectionFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == IConnectionIdFeatureType)
|
||||||
|
{
|
||||||
|
return _currentIConnectionIdFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == IConnectionTransportFeatureType)
|
||||||
|
{
|
||||||
|
return _currentIConnectionTransportFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == IConnectionApplicationFeatureType)
|
||||||
|
{
|
||||||
|
return _currentIConnectionApplicationFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExtraFeatureGet(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FastFeatureSet(Type key, object feature)
|
||||||
|
{
|
||||||
|
_featureRevision++;
|
||||||
|
|
||||||
|
if (key == IHttpConnectionFeatureType)
|
||||||
|
{
|
||||||
|
_currentIHttpConnectionFeature = feature;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == IConnectionIdFeatureType)
|
||||||
|
{
|
||||||
|
_currentIConnectionIdFeature = feature;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == IConnectionTransportFeatureType)
|
||||||
|
{
|
||||||
|
_currentIConnectionTransportFeature = feature;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == IConnectionApplicationFeatureType)
|
||||||
|
{
|
||||||
|
_currentIConnectionApplicationFeature = feature;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraFeatureSet(key, feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
|
||||||
|
{
|
||||||
|
if (_currentIHttpConnectionFeature != null)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<Type, object>(IHttpConnectionFeatureType, _currentIHttpConnectionFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentIConnectionIdFeature != null)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<Type, object>(IConnectionIdFeatureType, _currentIConnectionIdFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentIConnectionTransportFeature != null)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<Type, object>(IConnectionTransportFeatureType, _currentIConnectionTransportFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentIConnectionApplicationFeature != null)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<Type, object>(IConnectionApplicationFeatureType, _currentIConnectionApplicationFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MaybeExtra != null)
|
||||||
|
{
|
||||||
|
foreach (var item in MaybeExtra)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
||||||
|
{
|
||||||
|
public abstract partial class TransportConnection
|
||||||
|
{
|
||||||
|
public TransportConnection()
|
||||||
|
{
|
||||||
|
_currentIConnectionIdFeature = this;
|
||||||
|
_currentIConnectionTransportFeature = this;
|
||||||
|
_currentIHttpConnectionFeature = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAddress RemoteAddress { get; set; }
|
||||||
|
public int RemotePort { get; set; }
|
||||||
|
public IPAddress LocalAddress { get; set; }
|
||||||
|
public int LocalPort { get; set; }
|
||||||
|
|
||||||
|
public string ConnectionId { get; set; }
|
||||||
|
|
||||||
|
public virtual PipeFactory PipeFactory { get; }
|
||||||
|
public virtual IScheduler InputWriterScheduler { get; }
|
||||||
|
public virtual IScheduler OutputReaderScheduler { get; }
|
||||||
|
|
||||||
|
public IPipeConnection Transport { get; set; }
|
||||||
|
public IConnectionApplicationFeature Application => (IConnectionApplicationFeature)_currentIConnectionApplicationFeature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,15 +16,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="$(AspNetCoreVersion)" />
|
<ProjectReference Include="..\Protocols.Abstractions\Protocols.Abstractions.csproj" />
|
||||||
<PackageReference Include="System.Numerics.Vectors" Version="$(CoreFxVersion)" />
|
|
||||||
<PackageReference Include="System.Buffers" Version="$(CoreFxVersion)" />
|
|
||||||
<PackageReference Include="System.IO.Pipelines" Version="$(CoreFxLabVersion)" />
|
|
||||||
<PackageReference Include="System.Text.Encodings.Web.Utf8" Version="$(CoreFxLabVersion)" />
|
|
||||||
|
|
||||||
<!-- Override System.Memory and System.Runtime.CompilerServices.Unsafe to the ones we have on feed -->
|
|
||||||
<PackageReference Include="System.Memory" Version="$(CoreFxVersion)" />
|
|
||||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(CoreFxVersion)" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,16 @@ using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
public class LibuvConnection : LibuvConnectionContext
|
public partial class LibuvConnection : LibuvConnectionContext
|
||||||
{
|
{
|
||||||
private const int MinAllocBufferSize = 2048;
|
private const int MinAllocBufferSize = 2048;
|
||||||
|
|
||||||
|
|
@ -24,7 +25,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
(handle, suggestedsize, state) => AllocCallback(handle, suggestedsize, state);
|
(handle, suggestedsize, state) => AllocCallback(handle, suggestedsize, state);
|
||||||
|
|
||||||
private readonly UvStreamHandle _socket;
|
private readonly UvStreamHandle _socket;
|
||||||
private IConnectionContext _connectionContext;
|
|
||||||
|
|
||||||
private WritableBuffer? _currentWritableBuffer;
|
private WritableBuffer? _currentWritableBuffer;
|
||||||
private BufferHandle _bufferHandle;
|
private BufferHandle _bufferHandle;
|
||||||
|
|
@ -35,14 +35,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
|
|
||||||
if (_socket is UvTcpHandle tcpHandle)
|
if (_socket is UvTcpHandle tcpHandle)
|
||||||
{
|
{
|
||||||
RemoteEndPoint = tcpHandle.GetPeerIPEndPoint();
|
var remoteEndPoint = tcpHandle.GetPeerIPEndPoint();
|
||||||
LocalEndPoint = tcpHandle.GetSockIPEndPoint();
|
var localEndPoint = tcpHandle.GetSockIPEndPoint();
|
||||||
|
|
||||||
|
RemoteAddress = remoteEndPoint.Address;
|
||||||
|
RemotePort = remoteEndPoint.Port;
|
||||||
|
|
||||||
|
LocalAddress = localEndPoint.Address;
|
||||||
|
LocalPort = localEndPoint.Port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ConnectionId { get; set; }
|
public IPipeWriter Input => Application.Connection.Output;
|
||||||
public IPipeWriter Input { get; set; }
|
public IPipeReader Output => Application.Connection.Input;
|
||||||
public LibuvOutputConsumer Output { get; set; }
|
|
||||||
|
public LibuvOutputConsumer OutputConsumer { get; set; }
|
||||||
|
|
||||||
private ILibuvTrace Log => ListenerContext.TransportContext.Log;
|
private ILibuvTrace Log => ListenerContext.TransportContext.Log;
|
||||||
private IConnectionHandler ConnectionHandler => ListenerContext.TransportContext.ConnectionHandler;
|
private IConnectionHandler ConnectionHandler => ListenerContext.TransportContext.ConnectionHandler;
|
||||||
|
|
@ -52,11 +59,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_connectionContext = ConnectionHandler.OnConnection(this);
|
ConnectionHandler.OnConnection(this);
|
||||||
ConnectionId = _connectionContext.ConnectionId;
|
|
||||||
|
|
||||||
Input = _connectionContext.Input;
|
OutputConsumer = new LibuvOutputConsumer(Output, Thread, _socket, ConnectionId, Log);
|
||||||
Output = new LibuvOutputConsumer(_connectionContext.Output, Thread, _socket, ConnectionId, Log);
|
|
||||||
|
|
||||||
StartReading();
|
StartReading();
|
||||||
|
|
||||||
|
|
@ -67,7 +72,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
// This *must* happen after socket.ReadStart
|
// This *must* happen after socket.ReadStart
|
||||||
// The socket output consumer is the only thing that can close the connection. If the
|
// The socket output consumer is the only thing that can close the connection. If the
|
||||||
// output pipe is already closed by the time we start then it's fine since, it'll close gracefully afterwards.
|
// output pipe is already closed by the time we start then it's fine since, it'll close gracefully afterwards.
|
||||||
await Output.WriteOutputAsync();
|
await OutputConsumer.WriteOutputAsync();
|
||||||
}
|
}
|
||||||
catch (UvException ex)
|
catch (UvException ex)
|
||||||
{
|
{
|
||||||
|
|
@ -77,8 +82,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
// Now, complete the input so that no more reads can happen
|
// Now, complete the input so that no more reads can happen
|
||||||
Input.Complete(error ?? new ConnectionAbortedException());
|
Input.Complete(error ?? new ConnectionAbortedException());
|
||||||
_connectionContext.Output.Complete(error);
|
Output.Complete(error);
|
||||||
_connectionContext.OnConnectionClosed(error);
|
Application.OnConnectionClosed(error);
|
||||||
|
|
||||||
// Make sure it isn't possible for a paused read to resume reading after calling uv_close
|
// Make sure it isn't possible for a paused read to resume reading after calling uv_close
|
||||||
// on the stream handle
|
// on the stream handle
|
||||||
|
|
@ -173,7 +178,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_connectionContext.Abort(error);
|
Application.Abort(error);
|
||||||
// Complete after aborting the connection
|
// Complete after aborting the connection
|
||||||
Input.Complete(error);
|
Input.Complete(error);
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +216,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
Log.ConnectionReadFin(ConnectionId);
|
Log.ConnectionReadFin(ConnectionId);
|
||||||
var error = new IOException(ex.Message, ex);
|
var error = new IOException(ex.Message, ex);
|
||||||
|
|
||||||
_connectionContext.Abort(error);
|
Application.Abort(error);
|
||||||
Input.Complete(error);
|
Input.Complete(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,8 @@ using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
public class LibuvConnectionContext : IConnectionInformation
|
public class LibuvConnectionContext : TransportConnection
|
||||||
{
|
{
|
||||||
public LibuvConnectionContext()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LibuvConnectionContext(ListenerContext context)
|
public LibuvConnectionContext(ListenerContext context)
|
||||||
{
|
{
|
||||||
ListenerContext = context;
|
ListenerContext = context;
|
||||||
|
|
@ -20,11 +16,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
|
|
||||||
public ListenerContext ListenerContext { get; set; }
|
public ListenerContext ListenerContext { get; set; }
|
||||||
|
|
||||||
public IPEndPoint RemoteEndPoint { get; set; }
|
public override PipeFactory PipeFactory => ListenerContext.Thread.PipeFactory;
|
||||||
public IPEndPoint LocalEndPoint { get; set; }
|
public override IScheduler InputWriterScheduler => ListenerContext.Thread;
|
||||||
|
public override IScheduler OutputReaderScheduler => ListenerContext.Thread;
|
||||||
public PipeFactory PipeFactory => ListenerContext.Thread.PipeFactory;
|
|
||||||
public IScheduler InputWriterScheduler => ListenerContext.Thread;
|
|
||||||
public IScheduler OutputReaderScheduler => ListenerContext.Thread;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,15 @@ using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
{
|
{
|
||||||
internal sealed class SocketConnection : IConnectionInformation
|
internal sealed class SocketConnection : TransportConnection
|
||||||
{
|
{
|
||||||
private readonly Socket _socket;
|
private readonly Socket _socket;
|
||||||
private readonly SocketTransport _transport;
|
private readonly SocketTransport _transport;
|
||||||
private readonly IPEndPoint _localEndPoint;
|
|
||||||
private readonly IPEndPoint _remoteEndPoint;
|
|
||||||
private IConnectionContext _connectionContext;
|
|
||||||
private IPipeWriter _input;
|
private IPipeWriter _input;
|
||||||
private IPipeReader _output;
|
private IPipeReader _output;
|
||||||
private IList<ArraySegment<byte>> _sendBufferList;
|
private IList<ArraySegment<byte>> _sendBufferList;
|
||||||
|
|
@ -33,18 +32,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
_socket = socket;
|
_socket = socket;
|
||||||
_transport = transport;
|
_transport = transport;
|
||||||
|
|
||||||
_localEndPoint = (IPEndPoint)_socket.LocalEndPoint;
|
var localEndPoint = (IPEndPoint)_socket.LocalEndPoint;
|
||||||
_remoteEndPoint = (IPEndPoint)_socket.RemoteEndPoint;
|
var remoteEndPoint = (IPEndPoint)_socket.RemoteEndPoint;
|
||||||
|
|
||||||
|
LocalAddress = localEndPoint.Address;
|
||||||
|
LocalPort = localEndPoint.Port;
|
||||||
|
|
||||||
|
RemoteAddress = remoteEndPoint.Address;
|
||||||
|
RemotePort = remoteEndPoint.Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartAsync(IConnectionHandler connectionHandler)
|
public async Task StartAsync(IConnectionHandler connectionHandler)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_connectionContext = connectionHandler.OnConnection(this);
|
connectionHandler.OnConnection(this);
|
||||||
|
|
||||||
_input = _connectionContext.Input;
|
_input = Application.Connection.Output;
|
||||||
_output = _connectionContext.Output;
|
_output = Application.Connection.Input;
|
||||||
|
|
||||||
// Spawn send and receive logic
|
// Spawn send and receive logic
|
||||||
Task receiveTask = DoReceive();
|
Task receiveTask = DoReceive();
|
||||||
|
|
@ -130,7 +135,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_connectionContext.Abort(error);
|
Application.Abort(error);
|
||||||
_input.Complete(error);
|
_input.Complete(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +229,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_connectionContext.OnConnectionClosed(error);
|
Application.OnConnectionClosed(error);
|
||||||
_output.Complete(error);
|
_output.Complete(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -239,14 +244,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPEndPoint RemoteEndPoint => _remoteEndPoint;
|
public override PipeFactory PipeFactory => _transport.TransportFactory.PipeFactory;
|
||||||
|
public override IScheduler InputWriterScheduler => InlineScheduler.Default;
|
||||||
public IPEndPoint LocalEndPoint => _localEndPoint;
|
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
||||||
|
|
||||||
public PipeFactory PipeFactory => _transport.TransportFactory.PipeFactory;
|
|
||||||
|
|
||||||
public IScheduler InputWriterScheduler => InlineScheduler.Default;
|
|
||||||
|
|
||||||
public IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
|
{
|
||||||
|
public abstract class ConnectionContext
|
||||||
|
{
|
||||||
|
public abstract string ConnectionId { get; set; }
|
||||||
|
|
||||||
|
public abstract IFeatureCollection Features { get; }
|
||||||
|
|
||||||
|
public abstract IPipeConnection Transport { get; set; }
|
||||||
|
|
||||||
|
public abstract PipeFactory PipeFactory { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
|
{
|
||||||
|
public delegate Task ConnectionDelegate(ConnectionContext connection);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
|
{
|
||||||
|
public class DefaultConnectionContext : ConnectionContext
|
||||||
|
{
|
||||||
|
private FeatureReferences<FeatureInterfaces> _features;
|
||||||
|
|
||||||
|
public DefaultConnectionContext(IFeatureCollection features)
|
||||||
|
{
|
||||||
|
_features = new FeatureReferences<FeatureInterfaces>(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IConnectionIdFeature ConnectionIdFeature =>
|
||||||
|
_features.Fetch(ref _features.Cache.ConnectionId, _ => null);
|
||||||
|
|
||||||
|
private IConnectionTransportFeature ConnectionTransportFeature =>
|
||||||
|
_features.Fetch(ref _features.Cache.ConnectionTransport, _ => null);
|
||||||
|
|
||||||
|
public override string ConnectionId
|
||||||
|
{
|
||||||
|
get => ConnectionIdFeature.ConnectionId;
|
||||||
|
set => ConnectionIdFeature.ConnectionId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IFeatureCollection Features => _features.Collection;
|
||||||
|
|
||||||
|
public override PipeFactory PipeFactory => ConnectionTransportFeature.PipeFactory;
|
||||||
|
|
||||||
|
public override IPipeConnection Transport
|
||||||
|
{
|
||||||
|
get => ConnectionTransportFeature.Connection;
|
||||||
|
set => ConnectionTransportFeature.Connection = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FeatureInterfaces
|
||||||
|
{
|
||||||
|
public IConnectionIdFeature ConnectionId;
|
||||||
|
|
||||||
|
public IConnectionTransportFeature ConnectionTransport;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
{
|
{
|
||||||
public class AddressInUseException : InvalidOperationException
|
public class AddressInUseException : InvalidOperationException
|
||||||
{
|
{
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
{
|
{
|
||||||
public class ConnectionAbortedException : OperationCanceledException
|
public class ConnectionAbortedException : OperationCanceledException
|
||||||
{
|
{
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
{
|
{
|
||||||
public class ConnectionResetException : IOException
|
public class ConnectionResetException : IOException
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols.Features
|
||||||
|
{
|
||||||
|
public interface IConnectionApplicationFeature
|
||||||
|
{
|
||||||
|
IPipeConnection Connection { get; set; }
|
||||||
|
|
||||||
|
// TODO: Remove these (https://github.com/aspnet/KestrelHttpServer/issues/1772)
|
||||||
|
// REVIEW: These are around for now because handling pipe events messes with the order
|
||||||
|
// of operations an that breaks tons of tests. Instead, we preserve the existing semantics
|
||||||
|
// and ordering.
|
||||||
|
void Abort(Exception exception);
|
||||||
|
|
||||||
|
void OnConnectionClosed(Exception exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols.Features
|
||||||
|
{
|
||||||
|
public interface IConnectionIdFeature
|
||||||
|
{
|
||||||
|
string ConnectionId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols.Features
|
||||||
|
{
|
||||||
|
public interface IConnectionTransportFeature
|
||||||
|
{
|
||||||
|
PipeFactory PipeFactory { get; }
|
||||||
|
|
||||||
|
IPipeConnection Connection { get; set; }
|
||||||
|
|
||||||
|
IScheduler InputWriterScheduler { get; }
|
||||||
|
|
||||||
|
IScheduler OutputReaderScheduler { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Protocols
|
||||||
|
{
|
||||||
|
public interface IConnectionBuilder
|
||||||
|
{
|
||||||
|
IServiceProvider ApplicationServices { get; }
|
||||||
|
|
||||||
|
IConnectionBuilder Use(Func<ConnectionDelegate, ConnectionDelegate> middleware);
|
||||||
|
|
||||||
|
ConnectionDelegate Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace System.IO.Pipelines
|
||||||
|
{
|
||||||
|
public class PipeConnection : IPipeConnection
|
||||||
|
{
|
||||||
|
public PipeConnection(IPipeReader reader, IPipeWriter writer)
|
||||||
|
{
|
||||||
|
Input = reader;
|
||||||
|
Output = writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPipeReader Input { get; }
|
||||||
|
|
||||||
|
public IPipeWriter Output { get; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<AssemblyName>Microsoft.AspNetCore.Protocols.Abstractions</AssemblyName>
|
||||||
|
<RootNamespace>Microsoft.AspNetCore.Protocols.Abstractions</RootNamespace>
|
||||||
|
<Description>Core components of ASP.NET Core networking protocol stack.</Description>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<PackageTags>aspnetcore</PackageTags>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<NoWarn>CS1591;$(NoWarn)</NoWarn>
|
||||||
|
<EnableApiCheck>false</EnableApiCheck>
|
||||||
|
<!-- TODO: remove when https://github.com/dotnet/sdk/pull/1270 is fixed -->
|
||||||
|
<GenerateResourceMSBuildRuntime>CurrentRuntime</GenerateResourceMSBuildRuntime>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="$(AspNetCoreVersion)" />
|
||||||
|
<PackageReference Include="System.Numerics.Vectors" Version="$(CoreFxVersion)" />
|
||||||
|
<PackageReference Include="System.Buffers" Version="$(CoreFxVersion)" />
|
||||||
|
<PackageReference Include="System.IO.Pipelines" Version="$(CoreFxLabVersion)" />
|
||||||
|
<PackageReference Include="System.Text.Encodings.Web.Utf8" Version="$(CoreFxLabVersion)" />
|
||||||
|
|
||||||
|
<!-- Override System.Memory and System.Runtime.CompilerServices.Unsafe to the ones we have on feed -->
|
||||||
|
<PackageReference Include="System.Memory" Version="$(CoreFxVersion)" />
|
||||||
|
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(CoreFxVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
ConnectionId = "0123456789",
|
ConnectionId = "0123456789",
|
||||||
ConnectionAdapters = new List<IConnectionAdapter>(),
|
ConnectionAdapters = new List<IConnectionAdapter>(),
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = _pipeFactory,
|
||||||
{
|
|
||||||
PipeFactory = _pipeFactory
|
|
||||||
},
|
|
||||||
FrameConnectionId = long.MinValue,
|
FrameConnectionId = long.MinValue,
|
||||||
Input = _pipeFactory.Create(),
|
Input = _pipeFactory.Create(),
|
||||||
Output = _pipeFactory.Create(),
|
Output = _pipeFactory.Create(),
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
var frameContext = new FrameContext
|
var frameContext = new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = new TestServiceContext(),
|
ServiceContext = new TestServiceContext(),
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = new PipeFactory(),
|
||||||
{
|
|
||||||
PipeFactory = new PipeFactory()
|
|
||||||
},
|
|
||||||
TimeoutControl = null
|
TimeoutControl = null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
_frameContext = new FrameContext
|
_frameContext = new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = _serviceContext,
|
ServiceContext = _serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = _pipelineFactory,
|
||||||
{
|
|
||||||
PipeFactory = _pipelineFactory
|
|
||||||
},
|
|
||||||
TimeoutControl = _timeoutControl.Object,
|
TimeoutControl = _timeoutControl.Object,
|
||||||
Input = _input.Reader,
|
Input = _input.Reader,
|
||||||
Output = output
|
Output = output
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
ServiceContext = new TestServiceContext(),
|
ServiceContext = new TestServiceContext(),
|
||||||
Input = Pipe.Reader,
|
Input = Pipe.Reader,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = _pipelineFactory,
|
||||||
{
|
|
||||||
PipeFactory = _pipelineFactory
|
|
||||||
},
|
|
||||||
TimeoutControl = Mock.Of<ITimeoutControl>()
|
TimeoutControl = Mock.Of<ITimeoutControl>()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public IHttpSendFileFeature GetLastViaGeneric()
|
public IHttpSendFileFeature GetLastViaGeneric()
|
||||||
{
|
{
|
||||||
return _collection.Get<IHttpSendFileFeature> ();
|
return _collection.Get<IHttpSendFileFeature>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private object Get(Type type)
|
private object Get(Type type)
|
||||||
|
|
@ -85,10 +85,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
var frameContext = new FrameContext
|
var frameContext = new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = new PipeFactory()
|
||||||
{
|
|
||||||
PipeFactory = new PipeFactory()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_frame = new Frame<object>(application: null, frameContext: frameContext);
|
_frame = new Frame<object>(application: null, frameContext: frameContext);
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
var frameContext = new FrameContext
|
var frameContext = new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = new PipeFactory(),
|
||||||
{
|
|
||||||
PipeFactory = new PipeFactory()
|
|
||||||
},
|
|
||||||
TimeoutControl = new MockTimeoutControl()
|
TimeoutControl = new MockTimeoutControl()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,10 +90,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
var frame = new TestFrame<object>(application: null, context: new FrameContext
|
var frame = new TestFrame<object>(application: null, context: new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = pipeFactory,
|
||||||
{
|
|
||||||
PipeFactory = pipeFactory
|
|
||||||
},
|
|
||||||
Input = input.Reader,
|
Input = input.Reader,
|
||||||
Output = output
|
Output = output
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// 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.Net;
|
|
||||||
using System.IO.Pipelines;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|
||||||
{
|
|
||||||
public class MockConnectionInformation : IConnectionInformation
|
|
||||||
{
|
|
||||||
public IPEndPoint RemoteEndPoint { get; }
|
|
||||||
public IPEndPoint LocalEndPoint { get; }
|
|
||||||
|
|
||||||
public PipeFactory PipeFactory { get; set; }
|
|
||||||
public bool RequiresDispatch { get; }
|
|
||||||
public IScheduler InputWriterScheduler { get; }
|
|
||||||
public IScheduler OutputReaderScheduler { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -33,10 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
var frameContext = new FrameContext
|
var frameContext = new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = PipeFactory,
|
||||||
{
|
|
||||||
PipeFactory = PipeFactory
|
|
||||||
},
|
|
||||||
TimeoutControl = new MockTimeoutControl()
|
TimeoutControl = new MockTimeoutControl()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -177,10 +177,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
var frameContext = new FrameContext
|
var frameContext = new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = new PipeFactory()
|
||||||
{
|
|
||||||
PipeFactory = new PipeFactory()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var frame = new Frame<object>(application: null, frameContext: frameContext);
|
var frame = new Frame<object>(application: null, frameContext: frameContext);
|
||||||
|
|
|
||||||
|
|
@ -124,10 +124,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
var frame = new TestFrame<object>(application: null, context: new FrameContext
|
var frame = new TestFrame<object>(application: null, context: new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = pipeFactory,
|
||||||
{
|
|
||||||
PipeFactory = pipeFactory
|
|
||||||
},
|
|
||||||
TimeoutControl = new MockTimeoutControl(),
|
TimeoutControl = new MockTimeoutControl(),
|
||||||
Input = input.Reader,
|
Input = input.Reader,
|
||||||
Output = output
|
Output = output
|
||||||
|
|
|
||||||
|
|
@ -699,10 +699,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
var frame = new Frame<object>(null, new FrameContext
|
var frame = new Frame<object>(null, new FrameContext
|
||||||
{
|
{
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
ConnectionInformation = new MockConnectionInformation
|
PipeFactory = _pipeFactory,
|
||||||
{
|
|
||||||
PipeFactory = _pipeFactory
|
|
||||||
},
|
|
||||||
TimeoutControl = Mock.Of<ITimeoutControl>(),
|
TimeoutControl = Mock.Of<ITimeoutControl>(),
|
||||||
Output = pipe
|
Output = pipe
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Protocols;
|
||||||
|
using Microsoft.AspNetCore.Protocols.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
|
|
@ -12,26 +15,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
public PipeOptions InputOptions { get; set; } = new PipeOptions();
|
public PipeOptions InputOptions { get; set; } = new PipeOptions();
|
||||||
public PipeOptions OutputOptions { get; set; } = new PipeOptions();
|
public PipeOptions OutputOptions { get; set; } = new PipeOptions();
|
||||||
|
|
||||||
public IConnectionContext OnConnection(IConnectionInformation connectionInfo)
|
public void OnConnection(IFeatureCollection features)
|
||||||
{
|
{
|
||||||
Input = connectionInfo.PipeFactory.Create(InputOptions ?? new PipeOptions());
|
var connectionContext = new DefaultConnectionContext(features);
|
||||||
Output = connectionInfo.PipeFactory.Create(OutputOptions ?? new PipeOptions());
|
|
||||||
|
|
||||||
return new TestConnectionContext
|
Input = connectionContext.PipeFactory.Create(InputOptions ?? new PipeOptions());
|
||||||
|
Output = connectionContext.PipeFactory.Create(OutputOptions ?? new PipeOptions());
|
||||||
|
|
||||||
|
var context = new TestConnectionContext
|
||||||
{
|
{
|
||||||
Input = Input.Writer,
|
Connection = new PipeConnection(Output.Reader, Input.Writer)
|
||||||
Output = Output.Reader,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
connectionContext.Features.Set<IConnectionApplicationFeature>(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPipe Input { get; private set; }
|
public IPipe Input { get; private set; }
|
||||||
public IPipe Output { get; private set; }
|
public IPipe Output { get; private set; }
|
||||||
|
|
||||||
private class TestConnectionContext : IConnectionContext
|
private class TestConnectionContext : IConnectionApplicationFeature
|
||||||
{
|
{
|
||||||
public string ConnectionId { get; }
|
public string ConnectionId { get; }
|
||||||
public IPipeWriter Input { get; set; }
|
public IPipeConnection Connection { get; set; }
|
||||||
public IPipeReader Output { get; set; }
|
|
||||||
|
|
||||||
public void Abort(Exception ex)
|
public void Abort(Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
// 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.IO.Pipelines;
|
|
||||||
using System.Net;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Testing
|
|
||||||
{
|
|
||||||
public class MockConnectionInformation : IConnectionInformation
|
|
||||||
{
|
|
||||||
public IPEndPoint RemoteEndPoint { get; }
|
|
||||||
|
|
||||||
public IPEndPoint LocalEndPoint { get; }
|
|
||||||
|
|
||||||
public PipeFactory PipeFactory { get; set; }
|
|
||||||
|
|
||||||
public IScheduler InputWriterScheduler { get; }
|
|
||||||
|
|
||||||
public IScheduler OutputReaderScheduler { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue