Sockets transport (#2100)
* Make Sockets the default transport * Create separate Libuv and Sockets functional test projects * Fix functional tests that fail with Sockets * Moved OneToTenThreads test to Kestrel.Transport.Libuv.Tests * Fix systemd activation tests to use libuv transport * Dispose Sockets PipeFactory * Improve Socket's server-side abort handling * Add explicit rebinding test
This commit is contained in:
Родитель
d46d2ce193
Коммит
fdb4184dbf
|
@ -28,4 +28,4 @@ before_install:
|
|||
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi
|
||||
script:
|
||||
- ./build.sh
|
||||
- if test "$TRAVIS_OS_NAME" != "osx"; then bash test/Kestrel.FunctionalTests/SystemdActivation/docker.sh; fi
|
||||
- if test "$TRAVIS_OS_NAME" != "osx"; then bash test/SystemdActivation/docker.sh; fi
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26814.0
|
||||
VisualStudioVersion = 15.0.26730.16
|
||||
MinimumVisualStudioVersion = 15.0.26730.03
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -68,8 +68,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeGenerator", "tools\Code
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Https", "src\Kestrel.Https\Kestrel.Https.csproj", "{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.FunctionalTests", "test\Kestrel.FunctionalTests\Kestrel.FunctionalTests.csproj", "{9559A5F1-080C-4909-B6CF-7E4B3DC55748}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Performance", "benchmarks\Kestrel.Performance\Kestrel.Performance.csproj", "{EBFE9719-A44B-4978-A71F-D5C254E7F35A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestCertificates", "TestCertificates", "{2822C132-BFFB-4D53-AC5B-E7E47DD81A6E}"
|
||||
|
@ -112,6 +110,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{C2910A13
|
|||
build\repo.targets = build\repo.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SystemdActivation", "SystemdActivation", "{B7B0EA74-528F-46B8-9BC4-909D9A67C194}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
test\SystemdActivation\docker-entrypoint.sh = test\SystemdActivation\docker-entrypoint.sh
|
||||
test\SystemdActivation\docker.sh = test\SystemdActivation\docker.sh
|
||||
test\SystemdActivation\Dockerfile = test\SystemdActivation\Dockerfile
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Libuv.FunctionalTests", "test\Kestrel.Transport.Libuv.FunctionalTests\Kestrel.Trasnport.Libuv.FunctionalTests.csproj", "{74032D79-8EA7-4483-BD82-C38370420FFF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Sockets.FunctionalTests", "test\Kestrel.Transport.Sockets.FunctionalTests\Kestrel.Trasnport.Sockets.FunctionalTests.csproj", "{9C7B6B5F-088A-436E-834B-6373EA36DEEE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -194,18 +203,6 @@ Global
|
|||
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748}.Release|x86.Build.0 = Release|Any CPU
|
||||
{EBFE9719-A44B-4978-A71F-D5C254E7F35A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EBFE9719-A44B-4978-A71F-D5C254E7F35A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBFE9719-A44B-4978-A71F-D5C254E7F35A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
@ -314,6 +311,30 @@ Global
|
|||
{924AE57C-1EBA-4A1D-A039-8C100B7507A5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{924AE57C-1EBA-4A1D-A039-8C100B7507A5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{924AE57C-1EBA-4A1D-A039-8C100B7507A5}.Release|x86.Build.0 = Release|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -325,7 +346,6 @@ Global
|
|||
{B35D4D31-E74C-4646-8A11-7A7A40F0021E} = {8A3D00B8-1CCF-4BE6-A060-11104CE2D9CE}
|
||||
{BD2D4D29-1BD9-40D0-BB31-337D5416B63C} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
||||
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||
{9559A5F1-080C-4909-B6CF-7E4B3DC55748} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{EBFE9719-A44B-4978-A71F-D5C254E7F35A} = {A95C3BE1-B850-4265-97A0-777ADCCD437F}
|
||||
{2822C132-BFFB-4D53-AC5B-E7E47DD81A6E} = {0EF2ACDF-012F-4472-A13A-4272419E2903}
|
||||
{A76B8C8C-0DC5-4DD3-9B1F-02E51A0915F4} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||
|
@ -336,6 +356,9 @@ Global
|
|||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{6956CF5C-3163-4398-8628-4ECA569245B5} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||
{924AE57C-1EBA-4A1D-A039-8C100B7507A5} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||
{B7B0EA74-528F-46B8-9BC4-909D9A67C194} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{74032D79-8EA7-4483-BD82-C38370420FFF} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{9C7B6B5F-088A-436E-834B-6373EA36DEEE} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
@ -51,7 +52,7 @@ namespace SampleApp
|
|||
basePort = 5000;
|
||||
}
|
||||
|
||||
var host = new WebHostBuilder()
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.ConfigureLogging((_, factory) =>
|
||||
{
|
||||
factory.AddConsole();
|
||||
|
@ -80,16 +81,20 @@ namespace SampleApp
|
|||
// The following section should be used to demo sockets
|
||||
//options.ListenUnixSocket("/tmp/kestrel-test.sock");
|
||||
})
|
||||
.UseLibuv(options =>
|
||||
{
|
||||
// Uncomment the following line to change the default number of libuv threads for all endpoints.
|
||||
// options.ThreadCount = 4;
|
||||
})
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
.UseStartup<Startup>();
|
||||
|
||||
return host.RunAsync();
|
||||
if (string.Equals(Process.GetCurrentProcess().Id.ToString(), Environment.GetEnvironmentVariable("LISTEN_PID")))
|
||||
{
|
||||
// Use libuv if activated by systemd, since that's currently the only transport that supports being passed a socket handle.
|
||||
hostBuilder.UseLibuv(options =>
|
||||
{
|
||||
// Uncomment the following line to change the default number of libuv threads for all endpoints.
|
||||
// options.ThreadCount = 4;
|
||||
});
|
||||
}
|
||||
|
||||
return hostBuilder.Build().RunAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Core.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Kestrel.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
@ -3,4 +3,6 @@
|
|||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// 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 Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||
{
|
||||
public interface ISocketsTrace : ILogger
|
||||
{
|
||||
void ConnectionReadFin(string connectionId);
|
||||
|
||||
void ConnectionWriteFin(string connectionId);
|
||||
|
||||
void ConnectionError(string connectionId, Exception ex);
|
||||
|
||||
void ConnectionReset(string connectionId);
|
||||
|
||||
void ConnectionPause(string connectionId);
|
||||
|
||||
void ConnectionResume(string connectionId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// 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 Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||
{
|
||||
public class SocketsTrace : ISocketsTrace
|
||||
{
|
||||
// ConnectionRead: Reserved: 3
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _connectionPause =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, 4, @"Connection id ""{ConnectionId}"" paused.");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _connectionResume =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, 5, @"Connection id ""{ConnectionId}"" resumed.");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _connectionReadFin =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, 6, @"Connection id ""{ConnectionId}"" received FIN.");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _connectionWriteFin =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, 7, @"Connection id ""{ConnectionId}"" sending FIN.");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _connectionError =
|
||||
LoggerMessage.Define<string>(LogLevel.Information, 14, @"Connection id ""{ConnectionId}"" communication error.");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _connectionReset =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, 19, @"Connection id ""{ConnectionId}"" reset.");
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public SocketsTrace(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void ConnectionRead(string connectionId, int count)
|
||||
{
|
||||
// Don't log for now since this could be *too* verbose.
|
||||
// Reserved: Event ID 3
|
||||
}
|
||||
|
||||
public void ConnectionReadFin(string connectionId)
|
||||
{
|
||||
_connectionReadFin(_logger, connectionId, null);
|
||||
}
|
||||
|
||||
public void ConnectionWriteFin(string connectionId)
|
||||
{
|
||||
_connectionWriteFin(_logger, connectionId, null);
|
||||
}
|
||||
|
||||
public void ConnectionWrite(string connectionId, int count)
|
||||
{
|
||||
// Don't log for now since this could be *too* verbose.
|
||||
// Reserved: Event ID 11
|
||||
}
|
||||
|
||||
public void ConnectionWriteCallback(string connectionId, int status)
|
||||
{
|
||||
// Don't log for now since this could be *too* verbose.
|
||||
// Reserved: Event ID 12
|
||||
}
|
||||
|
||||
public void ConnectionError(string connectionId, Exception ex)
|
||||
{
|
||||
_connectionError(_logger, connectionId, ex);
|
||||
}
|
||||
|
||||
public void ConnectionReset(string connectionId)
|
||||
{
|
||||
_connectionReset(_logger, connectionId, null);
|
||||
}
|
||||
|
||||
public void ConnectionPause(string connectionId)
|
||||
{
|
||||
_connectionPause(_logger, connectionId, null);
|
||||
}
|
||||
|
||||
public void ConnectionResume(string connectionId)
|
||||
{
|
||||
_connectionResume(_logger, connectionId, null);
|
||||
}
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state) => _logger.BeginScope(state);
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => _logger.IsEnabled(logLevel);
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||
=> _logger.Log(logLevel, eventId, state, exception, formatter);
|
||||
}
|
||||
}
|
|
@ -5,30 +5,36 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO.Pipelines;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Protocols;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||
{
|
||||
internal sealed class SocketConnection : TransportConnection
|
||||
{
|
||||
private readonly Socket _socket;
|
||||
private readonly SocketTransport _transport;
|
||||
|
||||
private IList<ArraySegment<byte>> _sendBufferList;
|
||||
private const int MinAllocBufferSize = 2048;
|
||||
|
||||
internal SocketConnection(Socket socket, SocketTransport transport)
|
||||
private readonly Socket _socket;
|
||||
private readonly ISocketsTrace _trace;
|
||||
|
||||
private IList<ArraySegment<byte>> _sendBufferList;
|
||||
private volatile bool _aborted;
|
||||
|
||||
internal SocketConnection(Socket socket, PipeFactory pipeFactory, ISocketsTrace trace)
|
||||
{
|
||||
Debug.Assert(socket != null);
|
||||
Debug.Assert(transport != null);
|
||||
Debug.Assert(pipeFactory != null);
|
||||
Debug.Assert(trace != null);
|
||||
|
||||
_socket = socket;
|
||||
_transport = transport;
|
||||
PipeFactory = pipeFactory;
|
||||
_trace = trace;
|
||||
|
||||
var localEndPoint = (IPEndPoint)_socket.LocalEndPoint;
|
||||
var remoteEndPoint = (IPEndPoint)_socket.RemoteEndPoint;
|
||||
|
@ -40,6 +46,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
RemotePort = remoteEndPoint.Port;
|
||||
}
|
||||
|
||||
public override PipeFactory PipeFactory { get; }
|
||||
public override IScheduler InputWriterScheduler => InlineScheduler.Default;
|
||||
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
||||
|
||||
public async Task StartAsync(IConnectionHandler connectionHandler)
|
||||
{
|
||||
try
|
||||
|
@ -66,9 +76,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
// Dispose the socket(should noop if already called)
|
||||
_socket.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// TODO: Log
|
||||
_trace.LogError(0, ex, $"Unexpected exception in {nameof(SocketConnection)}.{nameof(StartAsync)}.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +100,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
if (bytesReceived == 0)
|
||||
{
|
||||
// FIN
|
||||
_trace.ConnectionReadFin(ConnectionId);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -100,7 +111,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
buffer.Commit();
|
||||
}
|
||||
|
||||
var result = await buffer.FlushAsync();
|
||||
var flushTask = buffer.FlushAsync();
|
||||
|
||||
if (!flushTask.IsCompleted)
|
||||
{
|
||||
_trace.ConnectionPause(ConnectionId);
|
||||
|
||||
await flushTask;
|
||||
|
||||
_trace.ConnectionResume(ConnectionId);
|
||||
}
|
||||
|
||||
var result = flushTask.GetAwaiter().GetResult();
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
// Pipe consumer is shut down, do we stop writing
|
||||
|
@ -111,25 +133,36 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionReset)
|
||||
{
|
||||
error = new ConnectionResetException(ex.Message, ex);
|
||||
_trace.ConnectionReset(ConnectionId);
|
||||
}
|
||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.OperationAborted)
|
||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.OperationAborted ||
|
||||
ex.SocketErrorCode == SocketError.Interrupted)
|
||||
{
|
||||
error = new ConnectionAbortedException();
|
||||
_trace.ConnectionError(ConnectionId, error);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
error = new ConnectionAbortedException();
|
||||
_trace.ConnectionError(ConnectionId, error);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
error = ex;
|
||||
_trace.ConnectionError(ConnectionId, error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = new IOException(ex.Message, ex);
|
||||
_trace.ConnectionError(ConnectionId, error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_aborted)
|
||||
{
|
||||
error = error ?? new ConnectionAbortedException();
|
||||
}
|
||||
|
||||
Input.Complete(error);
|
||||
}
|
||||
}
|
||||
|
@ -202,8 +235,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
Output.Advance(buffer.End);
|
||||
}
|
||||
}
|
||||
|
||||
_socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.OperationAborted)
|
||||
{
|
||||
|
@ -224,6 +255,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
finally
|
||||
{
|
||||
Output.Complete(error);
|
||||
|
||||
// Make sure to close the connection only after the _aborted flag is set.
|
||||
// Without this, the RequestsCanBeAbortedMidRead test will sometimes fail when
|
||||
// a BadHttpRequestException is thrown instead of a TaskCanceledException.
|
||||
_aborted = true;
|
||||
_trace.ConnectionWriteFin(ConnectionId);
|
||||
_socket.Shutdown(SocketShutdown.Both);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,8 +275,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
return segment;
|
||||
}
|
||||
|
||||
public override PipeFactory PipeFactory => _transport.TransportFactory.PipeFactory;
|
||||
public override IScheduler InputWriterScheduler => InlineScheduler.Default;
|
||||
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,32 +3,38 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Protocols;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||
{
|
||||
internal sealed class SocketTransport : ITransport
|
||||
{
|
||||
private readonly SocketTransportFactory _transportFactory;
|
||||
private readonly PipeFactory _pipeFactory = new PipeFactory();
|
||||
private readonly IEndPointInformation _endPointInformation;
|
||||
private readonly IConnectionHandler _handler;
|
||||
private readonly ISocketsTrace _trace;
|
||||
private Socket _listenSocket;
|
||||
private Task _listenTask;
|
||||
|
||||
internal SocketTransport(SocketTransportFactory transportFactory, IEndPointInformation endPointInformation, IConnectionHandler handler)
|
||||
internal SocketTransport(
|
||||
IEndPointInformation endPointInformation,
|
||||
IConnectionHandler handler,
|
||||
ISocketsTrace trace)
|
||||
{
|
||||
Debug.Assert(transportFactory != null);
|
||||
Debug.Assert(endPointInformation != null);
|
||||
Debug.Assert(endPointInformation.Type == ListenType.IPEndPoint);
|
||||
Debug.Assert(handler != null);
|
||||
Debug.Assert(trace != null);
|
||||
|
||||
_transportFactory = transportFactory;
|
||||
_endPointInformation = endPointInformation;
|
||||
_handler = handler;
|
||||
_trace = trace;
|
||||
|
||||
_listenSocket = null;
|
||||
_listenTask = null;
|
||||
|
@ -92,6 +98,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
|
||||
public Task StopAsync()
|
||||
{
|
||||
_pipeFactory.Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@ -105,7 +112,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
|
||||
acceptSocket.NoDelay = _endPointInformation.NoDelay;
|
||||
|
||||
var connection = new SocketConnection(acceptSocket, this);
|
||||
var connection = new SocketConnection(acceptSocket, _pipeFactory, _trace);
|
||||
_ = connection.StartAsync(_handler);
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +128,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal SocketTransportFactory TransportFactory => _transportFactory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,32 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO.Pipelines;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||
{
|
||||
public sealed class SocketTransportFactory : ITransportFactory
|
||||
{
|
||||
private readonly PipeFactory _pipeFactory = new PipeFactory();
|
||||
private readonly SocketsTrace _trace;
|
||||
|
||||
public SocketTransportFactory(IOptions<SocketTransportOptions> options)
|
||||
public SocketTransportFactory(
|
||||
IOptions<SocketTransportOptions> options,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
|
||||
var logger = loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets");
|
||||
_trace = new SocketsTrace(logger);
|
||||
}
|
||||
|
||||
public ITransport Create(IEndPointInformation endPointInformation, IConnectionHandler handler)
|
||||
|
@ -33,9 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
|||
throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
return new SocketTransport(this, endPointInformation, handler);
|
||||
return new SocketTransport(endPointInformation, handler, _trace);
|
||||
}
|
||||
|
||||
internal PipeFactory PipeFactory => _pipeFactory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,10 @@
|
|||
{
|
||||
"Name": "options",
|
||||
"Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions>"
|
||||
},
|
||||
{
|
||||
"Name": "loggerFactory",
|
||||
"Type": "Microsoft.Extensions.Logging.ILoggerFactory"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Kestrel.Core\Kestrel.Core.csproj" />
|
||||
<!-- Even though the Libuv transport is no longer used by default, it remains for back-compat -->
|
||||
<ProjectReference Include="..\Kestrel.Transport.Libuv\Kestrel.Transport.Libuv.csproj" />
|
||||
<ProjectReference Include="..\Kestrel.Transport.Sockets\Kestrel.Transport.Sockets.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -5,7 +5,10 @@ using System;
|
|||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
|
@ -23,10 +26,11 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
/// </returns>
|
||||
public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder)
|
||||
{
|
||||
hostBuilder.UseLibuv();
|
||||
|
||||
return hostBuilder.ConfigureServices(services =>
|
||||
{
|
||||
// Don't override an already-configured transport
|
||||
services.TryAddSingleton<ITransportFactory, SocketTransportFactory>();
|
||||
|
||||
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
|
||||
services.AddSingleton<IServer, KestrelServer>();
|
||||
});
|
||||
|
|
|
@ -163,7 +163,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
|
||||
private async Task RegisterAddresses_Success(string addressInput, string[] testUrls, int testPort = 0)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseUrls(addressInput)
|
||||
|
@ -223,7 +223,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
|
||||
private async Task RegisterIPEndPoint_Success(IPEndPoint endPoint, string testUrl, int testPort = 0)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
|
@ -304,7 +304,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel()
|
||||
.ConfigureLogging(builder => builder
|
||||
|
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
var port = ((IPEndPoint)socket.LocalEndPoint).Port;
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel()
|
||||
.UseUrls($"http://127.0.0.1:{port}")
|
||||
|
@ -359,7 +359,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
socket.Bind(new IPEndPoint(IPAddress.IPv6Loopback, 0));
|
||||
var port = ((IPEndPoint)socket.LocalEndPoint).Port;
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel()
|
||||
.UseUrls($"http://[::1]:{port}")
|
||||
|
@ -378,7 +378,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var useUrlsAddress = $"http://127.0.0.1:0";
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -417,7 +417,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var useUrlsAddress = $"http://127.0.0.1:0";
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
|
@ -455,7 +455,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Fact]
|
||||
public async Task DoesNotOverrideDirectConfigurationWithIServerAddressesFeature_IfAddressesEmpty()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
|
@ -499,7 +499,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Fact]
|
||||
public void ThrowsWhenBindingLocalhostToDynamicPort()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://localhost:0")
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
@ -515,7 +515,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[InlineData("ftp://localhost")]
|
||||
public void ThrowsForUnsupportedAddressFromHosting(string addr)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls(addr)
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
@ -526,6 +526,91 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
// https://github.com/dotnet/corefx/issues/24562
|
||||
[ConditionalFact]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Sockets transport fails to rebind on macOS.")]
|
||||
[OSSkipCondition(OperatingSystems.Linux, SkipReason = "Sockets transport fails to rebind on Linux.")]
|
||||
public async Task CanRebindToEndPoint()
|
||||
{
|
||||
var port = GetNextPort();
|
||||
var endPointAddress = $"http://127.0.0.1:{port}/";
|
||||
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, port);
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
{
|
||||
host.Start();
|
||||
|
||||
Assert.Equal(endPointAddress, await HttpClientSlim.GetStringAsync(endPointAddress));
|
||||
}
|
||||
|
||||
hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, port);
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
{
|
||||
host.Start();
|
||||
|
||||
Assert.Equal(endPointAddress, await HttpClientSlim.GetStringAsync(endPointAddress));
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/dotnet/corefx/issues/24562
|
||||
[ConditionalFact]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Sockets transport fails to rebind on macOS.")]
|
||||
[OSSkipCondition(OperatingSystems.Linux, SkipReason = "Sockets transport fails to rebind on Linux.")]
|
||||
public async Task CanRebindToMultipleEndPoints()
|
||||
{
|
||||
var port = GetNextPort();
|
||||
var ipv4endPointAddress = $"http://127.0.0.1:{port}/";
|
||||
var ipv6endPointAddress = $"http://[::1]:{port}/";
|
||||
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, port);
|
||||
options.Listen(IPAddress.IPv6Loopback, port);
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
{
|
||||
host.Start();
|
||||
|
||||
Assert.Equal(ipv4endPointAddress, await HttpClientSlim.GetStringAsync(ipv4endPointAddress));
|
||||
Assert.Equal(ipv6endPointAddress, await HttpClientSlim.GetStringAsync(ipv6endPointAddress));
|
||||
}
|
||||
|
||||
hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, port);
|
||||
options.Listen(IPAddress.IPv6Loopback, port);
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
{
|
||||
host.Start();
|
||||
|
||||
Assert.Equal(ipv4endPointAddress, await HttpClientSlim.GetStringAsync(ipv4endPointAddress));
|
||||
Assert.Equal(ipv6endPointAddress, await HttpClientSlim.GetStringAsync(ipv6endPointAddress));
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowsWhenBindingLocalhostToAddressInUse(AddressFamily addressFamily, IPAddress address)
|
||||
{
|
||||
using (var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp))
|
||||
|
@ -533,7 +618,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
socket.Bind(new IPEndPoint(address, 0));
|
||||
var port = ((IPEndPoint)socket.LocalEndPoint).Port;
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel()
|
||||
.UseUrls($"http://localhost:{port}")
|
||||
|
@ -807,6 +892,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
|
||||
private bool CanBindToPort()
|
||||
{
|
||||
#if MACOS && SOCKETS
|
||||
// Binding to a port with a Socket, disposing the Socket, and rebinding often fails with
|
||||
// SocketError.AddressAlreadyInUse on macOS. This isn't an issue if binding with libuv second.
|
||||
// https://github.com/dotnet/corefx/issues/24562
|
||||
return false;
|
||||
#else
|
||||
try
|
||||
{
|
||||
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
|
@ -819,6 +910,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
|
||||
private async Task TestSuccess(HttpProtocols serverProtocols, string request, string expectedResponse)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, 0, listenOptions => listenOptions.Protocols = serverProtocols);
|
||||
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
.Setup(provider => provider.CreateLogger(It.IsAny<string>()))
|
||||
.Returns(logger);
|
||||
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(loggingBuilder => loggingBuilder.AddProvider(loggerProvider.Object))
|
||||
.UseKestrel(options => options.Listen(IPAddress.Loopback, 0, listenOptions => listenOptions.Protocols = serverProtocols))
|
||||
.Configure(app => app.Run(context => Task.CompletedTask));
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
public async Task DoesNotThrowObjectDisposedExceptionOnConnectionAbort()
|
||||
{
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -153,7 +153,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
public async Task DoesNotThrowObjectDisposedExceptionOnEmptyConnection()
|
||||
{
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -236,7 +236,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
@ -265,7 +265,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
public async Task HandshakeTimesOutAndIsLoggedAsInformation()
|
||||
{
|
||||
var loggerProvider = new HandshakeErrorLoggerProvider();
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Fact]
|
||||
public async Task LoggingConnectionAdapterCanBeAddedBeforeAndAfterHttpsAdapter()
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
var host = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(builder =>
|
||||
{
|
||||
builder.SetMinimumLevel(LogLevel.Trace);
|
||||
|
|
|
@ -258,7 +258,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
TaskCompletionSource<object> startReadingRequestBody,
|
||||
TaskCompletionSource<object> clientFinishedSendingRequestBody)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
var host = TransportSelector.GetWebHostBuilder()
|
||||
.ConfigureLogging(_configureLoggingDelegate)
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
Assert.True(contentLength % bufferLength == 0, $"{nameof(contentLength)} sent must be evenly divisible by {bufferLength}.");
|
||||
Assert.True(bufferLength % 256 == 0, $"{nameof(bufferLength)} must be evenly divisible by 256");
|
||||
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Limits.MaxRequestBodySize = contentLength;
|
||||
|
@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Fact]
|
||||
public async Task DoesNotHangOnConnectionCloseRequest()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0")
|
||||
.Configure(app =>
|
||||
|
@ -185,7 +185,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
var requestBodyPersisted = false;
|
||||
var responseBodyPersisted = false;
|
||||
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0")
|
||||
.Configure(app =>
|
||||
|
@ -228,7 +228,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
public void CanUpgradeRequestWithConnectionKeepAliveUpgradeHeader()
|
||||
{
|
||||
var dataRead = false;
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0")
|
||||
.Configure(app =>
|
||||
|
@ -300,7 +300,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
.Setup(factory => factory.CreateLogger(It.IsAny<string>()))
|
||||
.Returns(Mock.Of<ILogger>());
|
||||
mockLoggerFactory
|
||||
.Setup(factory => factory.CreateLogger(It.IsIn("Microsoft.AspNetCore.Server.Kestrel", "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv")))
|
||||
.Setup(factory => factory.CreateLogger(It.IsIn("Microsoft.AspNetCore.Server.Kestrel",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets")))
|
||||
.Returns(mockLogger.Object);
|
||||
|
||||
using (var server = new TestServer(context => Task.CompletedTask, new TestServiceContext(mockLoggerFactory.Object)))
|
||||
|
@ -354,7 +356,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
.Setup(factory => factory.CreateLogger(It.IsAny<string>()))
|
||||
.Returns(Mock.Of<ILogger>());
|
||||
mockLoggerFactory
|
||||
.Setup(factory => factory.CreateLogger(It.IsIn("Microsoft.AspNetCore.Server.Kestrel", "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv")))
|
||||
.Setup(factory => factory.CreateLogger(It.IsIn("Microsoft.AspNetCore.Server.Kestrel",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets")))
|
||||
.Returns(mockLogger.Object);
|
||||
|
||||
using (var server = new TestServer(context => Task.CompletedTask, new TestServiceContext(mockLoggerFactory.Object)))
|
||||
|
@ -424,7 +428,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
.Setup(factory => factory.CreateLogger(It.IsAny<string>()))
|
||||
.Returns(Mock.Of<ILogger>());
|
||||
mockLoggerFactory
|
||||
.Setup(factory => factory.CreateLogger(It.IsIn("Microsoft.AspNetCore.Server.Kestrel", "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv")))
|
||||
.Setup(factory => factory.CreateLogger(It.IsIn("Microsoft.AspNetCore.Server.Kestrel",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets")))
|
||||
.Returns(mockLogger.Object);
|
||||
|
||||
using (var server = new TestServer(async context =>
|
||||
|
@ -464,7 +470,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
var appDone = new SemaphoreSlim(0);
|
||||
var expectedExceptionThrown = false;
|
||||
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0")
|
||||
.Configure(app => app.Run(async context =>
|
||||
|
@ -508,7 +514,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
var appStarted = new SemaphoreSlim(0);
|
||||
var requestAborted = new SemaphoreSlim(0);
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0")
|
||||
.Configure(app => app.Run(async context =>
|
||||
|
@ -538,7 +544,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Fact]
|
||||
public void AbortingTheConnectionSendsFIN()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0")
|
||||
.Configure(app => app.Run(context =>
|
||||
|
@ -1617,7 +1623,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
|
||||
private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
var builder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls($"http://{registerAddress}:0")
|
||||
.Configure(app =>
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Fact]
|
||||
public async Task LargeDownload()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0/")
|
||||
.Configure(app =>
|
||||
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
[Theory, MemberData(nameof(NullHeaderData))]
|
||||
public async Task IgnoreNullHeaderValues(string headerName, StringValues headerValue, string expectedValue)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0/")
|
||||
.Configure(app =>
|
||||
|
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
var onStartingCalled = false;
|
||||
var onCompletedCalled = false;
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0/")
|
||||
.Configure(app =>
|
||||
|
@ -179,7 +179,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
{
|
||||
InvalidOperationException ex = null;
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseUrls("http://127.0.0.1:0/")
|
||||
.Configure(app =>
|
||||
|
@ -2506,6 +2506,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
totalReceived += received;
|
||||
} while (received > 0 && totalReceived < responseSize);
|
||||
}
|
||||
catch (SocketException) { }
|
||||
catch (IOException)
|
||||
{
|
||||
// Socket.Receive could throw, and that is fine
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
_listenOptions = listenOptions;
|
||||
Context = context;
|
||||
|
||||
_host = new WebHostBuilder()
|
||||
_host = TransportSelector.GetWebHostBuilder()
|
||||
.UseKestrel(o =>
|
||||
{
|
||||
o.ListenOptions.Add(_listenOptions);
|
||||
|
|
|
@ -1,72 +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.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||
{
|
||||
public class ThreadCountTests
|
||||
{
|
||||
[ConditionalTheory]
|
||||
[MemberData(nameof(OneToTen))]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Tests fail on OS X due to low file descriptor limit.")]
|
||||
public async Task OneToTenThreads(int threadCount)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseLibuv(options =>
|
||||
{
|
||||
options.ThreadCount = threadCount;
|
||||
})
|
||||
.UseUrls("http://127.0.0.1:0/")
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
return context.Response.WriteAsync("Hello World");
|
||||
});
|
||||
});
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
{
|
||||
host.Start();
|
||||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
// Send 20 requests just to make sure we don't get any failures
|
||||
var requestTasks = new List<Task<string>>();
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
var requestTask = client.GetStringAsync($"http://127.0.0.1:{host.GetPort()}/");
|
||||
requestTasks.Add(requestTask);
|
||||
}
|
||||
|
||||
foreach (var result in await Task.WhenAll(requestTasks))
|
||||
{
|
||||
Assert.Equal("Hello World", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static TheoryData<int> OneToTen
|
||||
{
|
||||
get
|
||||
{
|
||||
var dataset = new TheoryData<int>();
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
dataset.Add(i);
|
||||
}
|
||||
return dataset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Microsoft.AspNetCore.Server.Kestrel.FunctionalTests</AssemblyName>
|
||||
<RootNamespace>Microsoft.AspNetCore.Server.Kestrel.FunctionalTests</RootNamespace>
|
||||
<AssemblyName>Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.FunctionalTests</AssemblyName>
|
||||
<RootNamespace>Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.FunctionalTests</RootNamespace>
|
||||
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
|
||||
<DefineConstants Condition="$([MSBuild]::IsOSPlatform('OSX'))">$(DefineConstants);MACOS</DefineConstants>
|
||||
|
@ -11,6 +11,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\shared\**\*.cs" />
|
||||
<Compile Include="..\Kestrel.FunctionalTests\**\*.cs" />
|
||||
<Content Include="..\shared\TestCertificates\*.pfx" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -20,6 +21,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Kestrel\Kestrel.csproj" />
|
||||
<ProjectReference Include="..\..\src\Kestrel.Transport.Libuv\Kestrel.Transport.Libuv.csproj" />
|
||||
<ProjectReference Include="..\..\src\Kestrel.Https\Kestrel.Https.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// 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 Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||
{
|
||||
public static class TransportSelector
|
||||
{
|
||||
public static IWebHostBuilder GetWebHostBuilder()
|
||||
{
|
||||
return new WebHostBuilder().UseLibuv();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -10,6 +13,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||
|
@ -25,6 +29,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> OneToTen => Enumerable.Range(1, 10).Select(i => new object[] { i });
|
||||
|
||||
[Fact]
|
||||
public async Task TransportCanBindAndStop()
|
||||
{
|
||||
|
@ -80,5 +86,49 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
|||
await transport.UnbindAsync();
|
||||
await transport.StopAsync();
|
||||
}
|
||||
|
||||
[ConditionalTheory]
|
||||
[MemberData(nameof(OneToTen))]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Tests fail on OS X due to low file descriptor limit.")]
|
||||
public async Task OneToTenThreads(int threadCount)
|
||||
{
|
||||
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
var serviceContext = new TestServiceContext();
|
||||
var testApplication = new DummyApplication(context =>
|
||||
{
|
||||
return context.Response.WriteAsync("Hello World");
|
||||
});
|
||||
|
||||
listenOptions.UseHttpServer(listenOptions.ConnectionAdapters, serviceContext, testApplication, HttpProtocols.Http1);
|
||||
|
||||
var transportContext = new TestLibuvTransportContext()
|
||||
{
|
||||
ConnectionHandler = new ConnectionHandler(serviceContext, listenOptions.Build()),
|
||||
Options = new LibuvTransportOptions { ThreadCount = threadCount }
|
||||
};
|
||||
|
||||
var transport = new LibuvTransport(transportContext, listenOptions);
|
||||
|
||||
await transport.BindAsync();
|
||||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
// Send 20 requests just to make sure we don't get any failures
|
||||
var requestTasks = new List<Task<string>>();
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
var requestTask = client.GetStringAsync($"http://127.0.0.1:{listenOptions.IPEndPoint.Port}/");
|
||||
requestTasks.Add(requestTask);
|
||||
}
|
||||
|
||||
foreach (var result in await Task.WhenAll(requestTasks))
|
||||
{
|
||||
Assert.Equal("Hello World", result);
|
||||
}
|
||||
}
|
||||
|
||||
await transport.UnbindAsync();
|
||||
await transport.StopAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.FunctionalTests</AssemblyName>
|
||||
<RootNamespace>Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.FunctionalTests</RootNamespace>
|
||||
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
|
||||
<DefineConstants Condition="$([MSBuild]::IsOSPlatform('OSX'))">$(DefineConstants);MACOS</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);SOCKETS</DefineConstants>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\shared\**\*.cs" />
|
||||
<Compile Include="..\Kestrel.FunctionalTests\**\*.cs" />
|
||||
<Content Include="..\shared\TestCertificates\*.pfx" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
|
||||
<ProjectReference Include="..\..\tools\CodeGenerator\CodeGenerator.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Kestrel\Kestrel.csproj" />
|
||||
<ProjectReference Include="..\..\src\Kestrel.Transport.Sockets\Kestrel.Transport.Sockets.csproj" />
|
||||
<ProjectReference Include="..\..\src\Kestrel.Https\Kestrel.Https.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Testing" />
|
||||
<PackageReference Include="Newtonsoft.Json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
// 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 Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||
{
|
||||
public static class TransportSelector
|
||||
{
|
||||
public static IWebHostBuilder GetWebHostBuilder()
|
||||
{
|
||||
return new WebHostBuilder().UseSockets();
|
||||
}
|
||||
}
|
||||
}
|
0
test/Kestrel.FunctionalTests/SystemdActivation/docker.sh → test/SystemdActivation/docker.sh
Executable file → Normal file
0
test/Kestrel.FunctionalTests/SystemdActivation/docker.sh → test/SystemdActivation/docker.sh
Executable file → Normal file
Загрузка…
Ссылка в новой задаче