Add Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions project (#1582).

- Changes the design to have one ConnectionHandler per endpoint.
This commit is contained in:
Cesar Blum Silveira 2017-04-03 15:09:03 -07:00 committed by GitHub
parent f285b18f08
commit 6bd0344880
42 changed files with 181 additions and 146 deletions

View File

@ -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.26228.9 VisualStudioVersion = 15.0.26327.1
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
@ -65,6 +65,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel", "src\Microsoft.AspNetCore.Server.Kestrel\Microsoft.AspNetCore.Server.Kestrel.csproj", "{56139957-5C29-4E7D-89BD-7D20598B4EAF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel", "src\Microsoft.AspNetCore.Server.Kestrel\Microsoft.AspNetCore.Server.Kestrel.csproj", "{56139957-5C29-4E7D-89BD-7D20598B4EAF}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions", "src\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj", "{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -195,6 +197,18 @@ Global
{56139957-5C29-4E7D-89BD-7D20598B4EAF}.Release|x64.Build.0 = Release|Any CPU {56139957-5C29-4E7D-89BD-7D20598B4EAF}.Release|x64.Build.0 = Release|Any CPU
{56139957-5C29-4E7D-89BD-7D20598B4EAF}.Release|x86.ActiveCfg = Release|Any CPU {56139957-5C29-4E7D-89BD-7D20598B4EAF}.Release|x86.ActiveCfg = Release|Any CPU
{56139957-5C29-4E7D-89BD-7D20598B4EAF}.Release|x86.Build.0 = Release|Any CPU {56139957-5C29-4E7D-89BD-7D20598B4EAF}.Release|x86.Build.0 = Release|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Debug|x64.ActiveCfg = Debug|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Debug|x64.Build.0 = Debug|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Debug|x86.ActiveCfg = Debug|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Debug|x86.Build.0 = Debug|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|Any CPU.Build.0 = Release|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x64.ActiveCfg = Release|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x64.Build.0 = Release|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x86.ActiveCfg = Release|Any CPU
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -212,5 +226,6 @@ Global
{2822C132-BFFB-4D53-AC5B-E7E47DD81A6E} = {0EF2ACDF-012F-4472-A13A-4272419E2903} {2822C132-BFFB-4D53-AC5B-E7E47DD81A6E} = {0EF2ACDF-012F-4472-A13A-4272419E2903}
{A76B8C8C-0DC5-4DD3-9B1F-02E51A0915F4} = {2D5D5227-4DBD-499A-96B1-76A36B03B750} {A76B8C8C-0DC5-4DD3-9B1F-02E51A0915F4} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
{56139957-5C29-4E7D-89BD-7D20598B4EAF} = {2D5D5227-4DBD-499A-96B1-76A36B03B750} {56139957-5C29-4E7D-89BD-7D20598B4EAF} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -5,17 +5,19 @@ using System.IO.Pipelines;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Internal
{ {
public class ConnectionHandler<TContext> : IConnectionHandler public class ConnectionHandler<TContext> : IConnectionHandler
{ {
private readonly ListenOptions _listenOptions;
private readonly ServiceContext _serviceContext; private readonly ServiceContext _serviceContext;
private readonly IHttpApplication<TContext> _application; private readonly IHttpApplication<TContext> _application;
public ConnectionHandler(ServiceContext serviceContext, IHttpApplication<TContext> application) public ConnectionHandler(ListenOptions listenOptions, ServiceContext serviceContext, IHttpApplication<TContext> application)
{ {
_listenOptions = listenOptions;
_serviceContext = serviceContext; _serviceContext = serviceContext;
_application = application; _application = application;
} }
@ -44,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
ConnectionId = connectionId, ConnectionId = connectionId,
ServiceContext = _serviceContext, ServiceContext = _serviceContext,
PipeFactory = connectionInfo.PipeFactory, PipeFactory = connectionInfo.PipeFactory,
ConnectionAdapters = connectionInfo.ListenOptions.ConnectionAdapters, ConnectionAdapters = _listenOptions.ConnectionAdapters,
Frame = frame, Frame = frame,
Input = inputPipe, Input = inputPipe,
Output = outputPipe, Output = outputPipe,
@ -52,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
}); });
_serviceContext.Log.ConnectionStart(connectionId); _serviceContext.Log.ConnectionStart(connectionId);
KestrelEventSource.Log.ConnectionStart(connection, connectionInfo); KestrelEventSource.Log.ConnectionStart(_listenOptions, connection, connectionInfo);
// 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.RequestProcessingAsync is guaranteed to unblock the transport thread before calling // Frame.RequestProcessingAsync is guaranteed to unblock the transport thread before calling

View File

@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Adapter.Internal; using Microsoft.AspNetCore.Server.Kestrel.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -16,7 +16,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Adapter; using Microsoft.AspNetCore.Server.Kestrel.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;

View File

@ -1,7 +1,7 @@
// 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.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
{ {

View File

@ -7,7 +7,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Exceptions; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http

View File

@ -4,7 +4,7 @@
using System.Diagnostics.Tracing; using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
{ {
@ -26,14 +26,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.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(ListenOptions listenOptions, IConnectionContext context, IConnectionInformation information)
{ {
// 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, context.ConnectionId,
information.ListenOptions.Scheme, listenOptions.Scheme,
information.LocalEndPoint.ToString(), information.LocalEndPoint.ToString(),
information.RemoteEndPoint.ToString()); information.RemoteEndPoint.ToString());
} }

View File

@ -16,8 +16,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Exceptions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -110,8 +109,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel
ServerOptions = Options ServerOptions = Options
}; };
var connectionHandler = new ConnectionHandler<TContext>(serviceContext, application);
var listenOptions = Options.ListenOptions; var listenOptions = Options.ListenOptions;
var hasListenOptions = listenOptions.Any(); var hasListenOptions = listenOptions.Any();
var hasServerAddresses = _serverAddresses.Addresses.Any(); var hasServerAddresses = _serverAddresses.Addresses.Any();
@ -128,7 +125,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
_logger.LogDebug($"No listening endpoints were configured. Binding to {Constants.DefaultServerAddress} by default."); _logger.LogDebug($"No listening endpoints were configured. Binding to {Constants.DefaultServerAddress} by default.");
// "localhost" for both IPv4 and IPv6 can't be represented as an IPEndPoint. // "localhost" for both IPv4 and IPv6 can't be represented as an IPEndPoint.
StartLocalhost(connectionHandler, ServerAddress.FromUrl(Constants.DefaultServerAddress)); StartLocalhost(ServerAddress.FromUrl(Constants.DefaultServerAddress), serviceContext, application);
// If StartLocalhost doesn't throw, there is at least one listener. // If StartLocalhost doesn't throw, there is at least one listener.
// The port cannot change for "localhost". // The port cannot change for "localhost".
@ -173,7 +170,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
if (string.Equals(parsedAddress.Host, "localhost", StringComparison.OrdinalIgnoreCase)) if (string.Equals(parsedAddress.Host, "localhost", StringComparison.OrdinalIgnoreCase))
{ {
// "localhost" for both IPv4 and IPv6 can't be represented as an IPEndPoint. // "localhost" for both IPv4 and IPv6 can't be represented as an IPEndPoint.
StartLocalhost(connectionHandler, parsedAddress); StartLocalhost(parsedAddress, serviceContext, application);
// If StartLocalhost doesn't throw, there is at least one listener. // If StartLocalhost doesn't throw, there is at least one listener.
// The port cannot change for "localhost". // The port cannot change for "localhost".
@ -193,6 +190,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
foreach (var endPoint in listenOptions) foreach (var endPoint in listenOptions)
{ {
var connectionHandler = new ConnectionHandler<TContext>(endPoint, serviceContext, application);
var transport = _transportFactory.Create(endPoint, connectionHandler); var transport = _transportFactory.Create(endPoint, connectionHandler);
_transports.Add(transport); _transports.Add(transport);
@ -256,7 +254,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
} }
} }
private void StartLocalhost<TContext>(ConnectionHandler<TContext> connectionHandler, ServerAddress parsedAddress) private void StartLocalhost<TContext>(ServerAddress parsedAddress, ServiceContext serviceContext, IHttpApplication<TContext> application)
{ {
if (parsedAddress.Port == 0) if (parsedAddress.Port == 0)
{ {
@ -272,6 +270,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
Scheme = parsedAddress.Scheme, Scheme = parsedAddress.Scheme,
}; };
var connectionHandler = new ConnectionHandler<TContext>(ipv4ListenOptions, serviceContext, application);
var transport = _transportFactory.Create(ipv4ListenOptions, connectionHandler); var transport = _transportFactory.Create(ipv4ListenOptions, connectionHandler);
_transports.Add(transport); _transports.Add(transport);
transport.BindAsync().Wait(); transport.BindAsync().Wait();
@ -293,6 +292,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
Scheme = parsedAddress.Scheme, Scheme = parsedAddress.Scheme,
}; };
var connectionHandler = new ConnectionHandler<TContext>(ipv6ListenOptions, serviceContext, application);
var transport = _transportFactory.Create(ipv6ListenOptions, connectionHandler); var transport = _transportFactory.Create(ipv6ListenOptions, connectionHandler);
_transports.Add(transport); _transports.Add(transport);
transport.BindAsync().Wait(); transport.BindAsync().Wait();

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Server.Kestrel.Adapter; using Microsoft.AspNetCore.Server.Kestrel.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
namespace Microsoft.AspNetCore.Server.Kestrel namespace Microsoft.AspNetCore.Server.Kestrel
{ {
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
/// Describes either an <see cref="IPEndPoint"/>, Unix domain socket path, or a file descriptor for an already open /// Describes either an <see cref="IPEndPoint"/>, Unix domain socket path, or a file descriptor for an already open
/// socket that Kestrel should bind to or open. /// socket that Kestrel should bind to or open.
/// </summary> /// </summary>
public class ListenOptions public class ListenOptions : IEndPointInformation
{ {
internal ListenOptions(IPEndPoint endPoint) internal ListenOptions(IPEndPoint endPoint)
{ {

View File

@ -25,6 +25,10 @@
<PackageReference Include="System.Text.Encodings.Web.Utf8" Version="$(CoreFxLabsVersion)" /> <PackageReference Include="System.Text.Encodings.Web.Utf8" Version="$(CoreFxLabsVersion)" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Diagnostics.Process" Version="$(CoreFxVersion)" /> <PackageReference Include="System.Diagnostics.Process" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.Thread" Version="$(CoreFxVersion)" /> <PackageReference Include="System.Threading.Thread" Version="$(CoreFxVersion)" />

View File

@ -3,7 +3,7 @@
using System; using System;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Exceptions namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public class AddressInUseException : InvalidOperationException public class AddressInUseException : InvalidOperationException
{ {

View File

@ -4,7 +4,7 @@
using System; using System;
using System.IO; using System.IO;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Exceptions namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public class ConnectionResetException : IOException public class ConnectionResetException : IOException
{ {

View File

@ -5,7 +5,7 @@ using System;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public interface IConnectionContext public interface IConnectionContext
{ {

View File

@ -1,7 +1,7 @@
// 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.
namespace Microsoft.AspNetCore.Server.Kestrel.Transport namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public interface IConnectionHandler public interface IConnectionHandler
{ {

View File

@ -3,13 +3,11 @@
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public interface IConnectionInformation public interface IConnectionInformation
{ {
ListenOptions ListenOptions { get; }
IPEndPoint RemoteEndPoint { get; } IPEndPoint RemoteEndPoint { get; }
IPEndPoint LocalEndPoint { get; } IPEndPoint LocalEndPoint { get; }

View File

@ -0,0 +1,39 @@
// 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;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{
public interface IEndPointInformation
{
/// <summary>
/// The type of interface being described: either an <see cref="IPEndPoint"/>, Unix domain socket path, or a file descriptor.
/// </summary>
ListenType Type { get; }
// IPEndPoint is mutable so port 0 can be updated to the bound port.
/// <summary>
/// The <see cref="IPEndPoint"/> to bind to.
/// Only set if <see cref="Type"/> is <see cref="ListenType.IPEndPoint"/>.
/// </summary>
IPEndPoint IPEndPoint { get; set; }
/// <summary>
/// The absolute path to a Unix domain socket to bind to.
/// Only set if <see cref="Type"/> is <see cref="ListenType.SocketPath"/>.
/// </summary>
string SocketPath { get; }
/// <summary>
/// A file descriptor for the socket to open.
/// Only set if <see cref="Type"/> is <see cref="ListenType.FileHandle"/>.
/// </summary>
ulong FileHandle { get; }
/// <summary>
/// Set to false to enable Nagle's algorithm for all connections.
/// </summary>
bool NoDelay { get; }
}
}

View File

@ -1,7 +1,7 @@
// 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.
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public interface ITimeoutControl public interface ITimeoutControl
{ {

View File

@ -3,7 +3,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public interface ITransport public interface ITransport
{ {

View File

@ -1,10 +1,10 @@
// 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.
namespace Microsoft.AspNetCore.Server.Kestrel.Transport namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public interface ITransportFactory public interface ITransportFactory
{ {
ITransport Create(ListenOptions listenOptions, IConnectionHandler handler); ITransport Create(IEndPointInformation endPointInformation, IConnectionHandler handler);
} }
} }

View File

@ -1,10 +1,10 @@
// 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.
namespace Microsoft.AspNetCore.Server.Kestrel namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
/// <summary> /// <summary>
/// Enumerates the <see cref="ListenOptions"/> types. /// Enumerates the <see cref="IEndPointInformation"/> types.
/// </summary> /// </summary>
public enum ListenType public enum ListenType
{ {

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Transport abstractions for the ASP.NET Core Kestrel cross-platform web server.</Description>
<TargetFrameworks>netstandard1.3</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;kestrel</PackageTags>
<NoWarn>CS1591;$(NoWarn)</NoWarn>
<EnableApiCheck>false</EnableApiCheck>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.IO.Pipelines" Version="$(CoreFxLabsPipelinesVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="$(AspNetCoreVersion)" />
</ItemGroup>
</Project>

View File

@ -1,7 +1,7 @@
// 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.
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
{ {
public enum TimeoutAction public enum TimeoutAction
{ {

View File

@ -9,8 +9,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Exceptions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http

View File

@ -3,7 +3,7 @@
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
{ {
@ -20,7 +20,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
public ListenerContext ListenerContext { get; set; } public ListenerContext ListenerContext { get; set; }
public ListenOptions ListenOptions => ListenerContext.ListenOptions;
public IPEndPoint RemoteEndPoint { get; set; } public IPEndPoint RemoteEndPoint { get; set; }
public IPEndPoint LocalEndPoint { get; set; } public IPEndPoint LocalEndPoint { get; set; }

View File

@ -5,6 +5,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -26,10 +27,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
public IKestrelTrace Log => TransportContext.Log; public IKestrelTrace Log => TransportContext.Log;
public Task StartAsync( public Task StartAsync(
ListenOptions listenOptions, IEndPointInformation endPointInformation,
KestrelThread thread) KestrelThread thread)
{ {
ListenOptions = listenOptions; EndPointInformation = endPointInformation;
Thread = thread; Thread = thread;
var tcs = new TaskCompletionSource<int>(this); var tcs = new TaskCompletionSource<int>(this);
@ -58,7 +59,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
/// </summary> /// </summary>
private UvStreamHandle CreateListenSocket() private UvStreamHandle CreateListenSocket()
{ {
switch (ListenOptions.Type) switch (EndPointInformation.Type)
{ {
case ListenType.IPEndPoint: case ListenType.IPEndPoint:
case ListenType.FileHandle: case ListenType.FileHandle:
@ -67,18 +68,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
try try
{ {
socket.Init(Thread.Loop, Thread.QueueCloseHandle); socket.Init(Thread.Loop, Thread.QueueCloseHandle);
socket.NoDelay(ListenOptions.NoDelay); socket.NoDelay(EndPointInformation.NoDelay);
if (ListenOptions.Type == ListenType.IPEndPoint) if (EndPointInformation.Type == ListenType.IPEndPoint)
{ {
socket.Bind(ListenOptions.IPEndPoint); socket.Bind(EndPointInformation.IPEndPoint);
// If requested port was "0", replace with assigned dynamic port. // If requested port was "0", replace with assigned dynamic port.
ListenOptions.IPEndPoint = socket.GetSockIPEndPoint(); EndPointInformation.IPEndPoint = socket.GetSockIPEndPoint();
} }
else else
{ {
socket.Open((IntPtr)ListenOptions.FileHandle); socket.Open((IntPtr)EndPointInformation.FileHandle);
} }
} }
catch catch
@ -94,7 +95,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
try try
{ {
pipe.Init(Thread.Loop, Thread.QueueCloseHandle, false); pipe.Init(Thread.Loop, Thread.QueueCloseHandle, false);
pipe.Bind(ListenOptions.SocketPath); pipe.Bind(EndPointInformation.SocketPath);
} }
catch catch
{ {

View File

@ -3,6 +3,7 @@
using System; using System;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
public LibuvTransportContext TransportContext { get; set; } public LibuvTransportContext TransportContext { get; set; }
public ListenOptions ListenOptions { get; set; } public IEndPointInformation EndPointInformation { get; set; }
public KestrelThread Thread { get; set; } public KestrelThread Thread { get; set; }
@ -25,13 +26,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
/// </summary> /// </summary>
protected UvStreamHandle CreateAcceptSocket() protected UvStreamHandle CreateAcceptSocket()
{ {
switch (ListenOptions.Type) switch (EndPointInformation.Type)
{ {
case ListenType.IPEndPoint: case ListenType.IPEndPoint:
case ListenType.FileHandle: case ListenType.FileHandle:
var tcpHandle = new UvTcpHandle(TransportContext.Log); var tcpHandle = new UvTcpHandle(TransportContext.Log);
tcpHandle.Init(Thread.Loop, Thread.QueueCloseHandle); tcpHandle.Init(Thread.Loop, Thread.QueueCloseHandle);
tcpHandle.NoDelay(ListenOptions.NoDelay); tcpHandle.NoDelay(EndPointInformation.NoDelay);
return tcpHandle; return tcpHandle;
case ListenType.SocketPath: case ListenType.SocketPath:
var pipeHandle = new UvPipeHandle(TransportContext.Log); var pipeHandle = new UvPipeHandle(TransportContext.Log);

View File

@ -8,6 +8,7 @@ using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -39,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
public async Task StartAsync( public async Task StartAsync(
string pipeName, string pipeName,
byte[] pipeMessage, byte[] pipeMessage,
ListenOptions listenOptions, IEndPointInformation endPointInformation,
KestrelThread thread) KestrelThread thread)
{ {
_pipeName = pipeName; _pipeName = pipeName;
@ -52,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
Marshal.StructureToPtr(fileCompletionInfo, _fileCompletionInfoPtr, false); Marshal.StructureToPtr(fileCompletionInfo, _fileCompletionInfoPtr, false);
} }
await StartAsync(listenOptions, thread).ConfigureAwait(false); await StartAsync(endPointInformation, thread).ConfigureAwait(false);
await Thread.PostAsync(state => ((ListenerPrimary)state).PostCallback(), await Thread.PostAsync(state => ((ListenerPrimary)state).PostCallback(),
this).ConfigureAwait(false); this).ConfigureAwait(false);

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -36,14 +37,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
public Task StartAsync( public Task StartAsync(
string pipeName, string pipeName,
byte[] pipeMessage, byte[] pipeMessage,
ListenOptions listenOptions, IEndPointInformation endPointInformation,
KestrelThread thread) KestrelThread thread)
{ {
_pipeName = pipeName; _pipeName = pipeName;
_pipeMessage = pipeMessage; _pipeMessage = pipeMessage;
_buf = thread.Loop.Libuv.buf_init(_ptr, 4); _buf = thread.Loop.Libuv.buf_init(_ptr, 4);
ListenOptions = listenOptions; EndPointInformation = endPointInformation;
Thread = thread; Thread = thread;
DispatchPipe = new UvPipeHandle(Log); DispatchPipe = new UvPipeHandle(Log);

View File

@ -3,6 +3,7 @@
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
{ {

View File

@ -9,8 +9,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Exceptions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -19,21 +18,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
{ {
public class KestrelEngine : ITransport public class KestrelEngine : ITransport
{ {
private readonly ListenOptions _listenOptions; private readonly IEndPointInformation _endPointInformation;
private readonly List<IAsyncDisposable> _listeners = new List<IAsyncDisposable>(); private readonly List<IAsyncDisposable> _listeners = new List<IAsyncDisposable>();
public KestrelEngine(LibuvTransportContext context, ListenOptions listenOptions) public KestrelEngine(LibuvTransportContext context, IEndPointInformation endPointInformation)
: this(new LibuvFunctions(), context, listenOptions) : this(new LibuvFunctions(), context, endPointInformation)
{ } { }
// For testing // For testing
public KestrelEngine(LibuvFunctions uv, LibuvTransportContext context, ListenOptions listenOptions) public KestrelEngine(LibuvFunctions uv, LibuvTransportContext context, IEndPointInformation endPointInformation)
{ {
Libuv = uv; Libuv = uv;
TransportContext = context; TransportContext = context;
_listenOptions = listenOptions; _endPointInformation = endPointInformation;
} }
public LibuvFunctions Libuv { get; } public LibuvFunctions Libuv { get; }
@ -92,7 +91,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
{ {
var listener = new Listener(TransportContext); var listener = new Listener(TransportContext);
_listeners.Add(listener); _listeners.Add(listener);
await listener.StartAsync(_listenOptions, Threads[0]).ConfigureAwait(false); await listener.StartAsync(_endPointInformation, Threads[0]).ConfigureAwait(false);
} }
else else
{ {
@ -101,13 +100,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
var listenerPrimary = new ListenerPrimary(TransportContext); var listenerPrimary = new ListenerPrimary(TransportContext);
_listeners.Add(listenerPrimary); _listeners.Add(listenerPrimary);
await listenerPrimary.StartAsync(pipeName, pipeMessage, _listenOptions, Threads[0]).ConfigureAwait(false); await listenerPrimary.StartAsync(pipeName, pipeMessage, _endPointInformation, Threads[0]).ConfigureAwait(false);
foreach (var thread in Threads.Skip(1)) foreach (var thread in Threads.Skip(1))
{ {
var listenerSecondary = new ListenerSecondary(TransportContext); var listenerSecondary = new ListenerSecondary(TransportContext);
_listeners.Add(listenerSecondary); _listeners.Add(listenerSecondary);
await listenerSecondary.StartAsync(pipeName, pipeMessage, _listenOptions, thread).ConfigureAwait(false); await listenerSecondary.StartAsync(pipeName, pipeMessage, _endPointInformation, thread).ConfigureAwait(false);
} }
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -65,7 +66,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
}; };
} }
public ITransport Create(ListenOptions listenOptions, IConnectionHandler handler) public ITransport Create(IEndPointInformation endPointInformation, IConnectionHandler handler)
{ {
var transportContext = new LibuvTransportContext var transportContext = new LibuvTransportContext
{ {
@ -75,7 +76,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
ConnectionHandler = handler ConnectionHandler = handler
}; };
return new KestrelEngine(transportContext, listenOptions); return new KestrelEngine(transportContext, endPointInformation);
} }
} }
} }

View File

@ -2,7 +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 Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv; using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;

View File

@ -3,14 +3,12 @@
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
public class MockConnectionInformation : IConnectionInformation public class MockConnectionInformation : IConnectionInformation
{ {
public ListenOptions ListenOptions { get; }
public IPEndPoint RemoteEndPoint { get; } public IPEndPoint RemoteEndPoint { get; }
public IPEndPoint LocalEndPoint { get; } public IPEndPoint LocalEndPoint { get; }

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public async Task ListenerCanCreateAndDispose(ListenOptions listenOptions) public async Task ListenerCanCreateAndDispose(ListenOptions listenOptions)
{ {
var testContext = new TestServiceContext(); var testContext = new TestServiceContext();
testContext.App = TestApp.EchoApp; testContext.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(listenOptions, testContext, new DummyApplication(TestApp.EchoApp));
var engine = new KestrelEngine(testContext.TransportContext, listenOptions); var engine = new KestrelEngine(testContext.TransportContext, listenOptions);
await engine.BindAsync(); await engine.BindAsync();
@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public async Task ConnectionCanReadAndWrite(ListenOptions listenOptions) public async Task ConnectionCanReadAndWrite(ListenOptions listenOptions)
{ {
var testContext = new TestServiceContext(); var testContext = new TestServiceContext();
testContext.App = TestApp.EchoApp; testContext.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(listenOptions, testContext, new DummyApplication(TestApp.EchoApp));
var engine = new KestrelEngine(testContext.TransportContext, listenOptions); var engine = new KestrelEngine(testContext.TransportContext, listenOptions);
await engine.BindAsync(); await engine.BindAsync();

View File

@ -16,7 +16,7 @@ using Microsoft.AspNetCore.Server.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -712,7 +712,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
private class MockConnectionInformation : IConnectionInformation private class MockConnectionInformation : IConnectionInformation
{ {
public ListenOptions ListenOptions { get; }
public IPEndPoint RemoteEndPoint { get; } public IPEndPoint RemoteEndPoint { get; }
public IPEndPoint LocalEndPoint { get; } public IPEndPoint LocalEndPoint { get; }
public PipeFactory PipeFactory { get; } public PipeFactory PipeFactory { get; }

View File

@ -4,17 +4,17 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Server.Kestrel; using Microsoft.AspNetCore.Server.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Moq; using Moq;
using Xunit; using Xunit;
using Microsoft.AspNetCore.Builder;
namespace Microsoft.AspNetCore.Server.KestrelTests namespace Microsoft.AspNetCore.Server.KestrelTests
{ {
@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
private class MockTransportFactory : ITransportFactory private class MockTransportFactory : ITransportFactory
{ {
public ITransport Create(ListenOptions listenOptions, IConnectionHandler handler) public ITransport Create(IEndPointInformation endPointInformation, IConnectionHandler handler)
{ {
return Mock.Of<ITransport>(); return Mock.Of<ITransport>();
} }

View File

@ -6,9 +6,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel; using Microsoft.AspNetCore.Server.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
@ -26,18 +24,16 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public async Task ConnectionsGetRoundRobinedToSecondaryListeners() public async Task ConnectionsGetRoundRobinedToSecondaryListeners()
{ {
var libuv = new LibuvFunctions(); var libuv = new LibuvFunctions();
var serviceContextPrimary = new TestServiceContext
{
App = c => c.Response.WriteAsync("Primary")
};
var serviceContextSecondary = new TestServiceContext
{
App = c => c.Response.WriteAsync("Secondary")
};
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)); var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
var serviceContextPrimary = new TestServiceContext();
serviceContextPrimary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
var serviceContextSecondary = new TestServiceContext();
serviceContextSecondary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
var kestrelEngine = new KestrelEngine(libuv, serviceContextPrimary.TransportContext, listenOptions); var kestrelEngine = new KestrelEngine(libuv, serviceContextPrimary.TransportContext, listenOptions);
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n"); var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
@ -80,11 +76,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public async Task NonListenerPipeConnectionsAreLoggedAndIgnored() public async Task NonListenerPipeConnectionsAreLoggedAndIgnored()
{ {
var libuv = new LibuvFunctions(); var libuv = new LibuvFunctions();
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
var serviceContextPrimary = new TestServiceContext var serviceContextPrimary = new TestServiceContext();
{ serviceContextPrimary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
App = c => c.Response.WriteAsync("Primary") listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
};
var serviceContextSecondary = new TestServiceContext var serviceContextSecondary = new TestServiceContext
{ {
@ -92,10 +88,10 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
ServerOptions = serviceContextPrimary.ServerOptions, ServerOptions = serviceContextPrimary.ServerOptions,
ThreadPool = serviceContextPrimary.ThreadPool, ThreadPool = serviceContextPrimary.ThreadPool,
HttpParserFactory = serviceContextPrimary.HttpParserFactory, HttpParserFactory = serviceContextPrimary.HttpParserFactory,
App = c => c.Response.WriteAsync("Secondary")
}; };
serviceContextSecondary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
var kestrelEngine = new KestrelEngine(libuv, serviceContextPrimary.TransportContext, listenOptions); var kestrelEngine = new KestrelEngine(libuv, serviceContextPrimary.TransportContext, listenOptions);
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n"); var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
@ -187,11 +183,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public async Task PipeConnectionsWithWrongMessageAreLoggedAndIgnored() public async Task PipeConnectionsWithWrongMessageAreLoggedAndIgnored()
{ {
var libuv = new LibuvFunctions(); var libuv = new LibuvFunctions();
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
var serviceContextPrimary = new TestServiceContext var serviceContextPrimary = new TestServiceContext();
{ serviceContextPrimary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
App = c => c.Response.WriteAsync("Primary") listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
};
var serviceContextSecondary = new TestServiceContext var serviceContextSecondary = new TestServiceContext
{ {
@ -199,10 +195,10 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
ServerOptions = serviceContextPrimary.ServerOptions, ServerOptions = serviceContextPrimary.ServerOptions,
ThreadPool = serviceContextPrimary.ThreadPool, ThreadPool = serviceContextPrimary.ThreadPool,
HttpParserFactory = serviceContextPrimary.HttpParserFactory, HttpParserFactory = serviceContextPrimary.HttpParserFactory,
App = c => c.Response.WriteAsync("Secondary")
}; };
serviceContextSecondary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
var kestrelEngine = new KestrelEngine(libuv, serviceContextPrimary.TransportContext, listenOptions); var kestrelEngine = new KestrelEngine(libuv, serviceContextPrimary.TransportContext, listenOptions);
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n"); var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
@ -271,29 +267,5 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
Assert.True(false, $"'{address}' failed to respond with '{expected}' in {maxRetries} retries."); Assert.True(false, $"'{address}' failed to respond with '{expected}' in {maxRetries} retries.");
} }
private class TestApplication : IHttpApplication<DefaultHttpContext>
{
private readonly Func<DefaultHttpContext, Task> _app;
public TestApplication(Func<DefaultHttpContext, Task> app)
{
_app = app;
}
public DefaultHttpContext CreateContext(IFeatureCollection contextFeatures)
{
return new DefaultHttpContext(contextFeatures);
}
public Task ProcessRequestAsync(DefaultHttpContext context)
{
return _app(context);
}
public void DisposeContext(DefaultHttpContext context, Exception exception)
{
}
}
} }
} }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize; serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize;
serviceContext.ThreadPool = new LoggingThreadPool(null); serviceContext.ThreadPool = new LoggingThreadPool(null);
var connectionHandler = new ConnectionHandler<object>(serviceContext, application: null); var connectionHandler = new ConnectionHandler<object>(listenOptions: null, serviceContext: serviceContext, application: null);
var mockScheduler = Mock.Of<IScheduler>(); var mockScheduler = Mock.Of<IScheduler>();
var outputPipeOptions = connectionHandler.GetOutputPipeOptions(mockScheduler); var outputPipeOptions = connectionHandler.GetOutputPipeOptions(mockScheduler);
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize; serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
serviceContext.ThreadPool = new LoggingThreadPool(null); serviceContext.ThreadPool = new LoggingThreadPool(null);
var connectionHandler = new ConnectionHandler<object>(serviceContext, application: null); var connectionHandler = new ConnectionHandler<object>(listenOptions: null, serviceContext: serviceContext, application: null);
var mockScheduler = Mock.Of<IScheduler>(); var mockScheduler = Mock.Of<IScheduler>();
var inputPipeOptions = connectionHandler.GetInputPipeOptions(mockScheduler); var inputPipeOptions = connectionHandler.GetInputPipeOptions(mockScheduler);

View File

@ -4,7 +4,7 @@
using System; using System;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Transport; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers

View File

@ -7,6 +7,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;

View File

@ -43,8 +43,7 @@ namespace Microsoft.AspNetCore.Testing
_listenOptions = listenOptions; _listenOptions = listenOptions;
Context = context; Context = context;
Context.App = app; Context.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(listenOptions, Context, new DummyApplication(app, httpContextFactory));
Context.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(Context, new DummyApplication(app, httpContextFactory));
try try
{ {

View File

@ -14,8 +14,6 @@ namespace Microsoft.AspNetCore.Testing
{ {
public class TestServiceContext : ServiceContext public class TestServiceContext : ServiceContext
{ {
private RequestDelegate _app;
public TestServiceContext() public TestServiceContext()
{ {
Log = new TestKestrelTrace(); Log = new TestKestrelTrace();
@ -43,18 +41,5 @@ namespace Microsoft.AspNetCore.Testing
public string DateHeaderValue { get; } public string DateHeaderValue { get; }
public LibuvTransportContext TransportContext { get; } public LibuvTransportContext TransportContext { get; }
public RequestDelegate App
{
get
{
return _app;
}
set
{
TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(this, new DummyApplication(value));
_app = value;
}
}
} }
} }