Initial work to support HTTPS using SslStream
- Add extension method "UseKestrelHttps" to IApplicationBuilder
This commit is contained in:
parent
49451fb11e
commit
2f3a00625a
|
|
@ -33,6 +33,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.StandardsPolice",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Server.Kestrel.LibuvCopier", "tools\Microsoft.AspNet.Server.Kestrel.LibuvCopier\Microsoft.AspNet.Server.Kestrel.LibuvCopier.xproj", "{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Server.Kestrel.LibuvCopier", "tools\Microsoft.AspNet.Server.Kestrel.LibuvCopier\Microsoft.AspNet.Server.Kestrel.LibuvCopier.xproj", "{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Server.Kestrel.Https", "src\Microsoft.AspNet.Server.Kestrel.Https\Microsoft.AspNet.Server.Kestrel.Https.xproj", "{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -67,6 +69,10 @@ Global
|
||||||
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -79,5 +85,6 @@ Global
|
||||||
{BD2D4D29-1BD9-40D0-BB31-337D5416B63C} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
{BD2D4D29-1BD9-40D0-BB31-337D5416B63C} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
||||||
{82295647-7C1C-4671-BAB6-0FEF58F949EC} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
{82295647-7C1C-4671-BAB6-0FEF58F949EC} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
||||||
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
{8CBA6FE3-3CC9-4420-8AA3-123E983734C2} = {327F7880-D9AF-46BD-B45C-3B7E34A01DFD}
|
||||||
|
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@
|
||||||
"Microsoft.Extensions.Logging.Console": "1.0.0-*"
|
"Microsoft.Extensions.Logging.Console": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnx451": { },
|
"dnx451": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.AspNet.Server.Kestrel.Https": "1.0.0-*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dnxcore50": {
|
"dnxcore50": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Console": "4.0.0-beta-*"
|
"System.Console": "4.0.0-beta-*"
|
||||||
|
|
@ -16,6 +20,6 @@
|
||||||
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel",
|
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel",
|
||||||
"run": "Microsoft.AspNet.Server.Kestrel",
|
"run": "Microsoft.AspNet.Server.Kestrel",
|
||||||
"run-socket": "Microsoft.AspNet.Server.Kestrel --server.urls http://unix:/tmp/kestrel-test.sock",
|
"run-socket": "Microsoft.AspNet.Server.Kestrel --server.urls http://unix:/tmp/kestrel-test.sock",
|
||||||
"kestrel": "Microsoft.AspNet.Server.Kestrel"
|
"kestrel": "Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000;https://localhost:5001"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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.Security.Cryptography.X509Certificates;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Http.Features;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Https
|
||||||
|
{
|
||||||
|
public static class HttpsApplicationBuilderExtensions
|
||||||
|
{
|
||||||
|
public static IApplicationBuilder UseKestrelHttps(this IApplicationBuilder app, X509Certificate2 cert)
|
||||||
|
{
|
||||||
|
var serverInfo = app.ServerFeatures.Get<IKestrelServerInformation>();
|
||||||
|
|
||||||
|
if (serverInfo == null)
|
||||||
|
{
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prevFilter = serverInfo.ConnectionFilter ?? new NoOpConnectionFilter();
|
||||||
|
|
||||||
|
serverInfo.ConnectionFilter = new HttpsConnectionFilter(cert, prevFilter);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Https
|
||||||
|
{
|
||||||
|
public class HttpsConnectionFilter : IConnectionFilter
|
||||||
|
{
|
||||||
|
private readonly X509Certificate2 _cert;
|
||||||
|
private readonly IConnectionFilter _previous;
|
||||||
|
|
||||||
|
public HttpsConnectionFilter(X509Certificate2 cert, IConnectionFilter previous)
|
||||||
|
{
|
||||||
|
if (cert == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(cert));
|
||||||
|
}
|
||||||
|
if (previous == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(previous));
|
||||||
|
}
|
||||||
|
|
||||||
|
_cert = cert;
|
||||||
|
_previous = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnConnection(ConnectionFilterContext context)
|
||||||
|
{
|
||||||
|
await _previous.OnConnection(context);
|
||||||
|
|
||||||
|
if (string.Equals(context.Address.Scheme, "https", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var sslStream = new SslStream(context.Connection);
|
||||||
|
await sslStream.AuthenticateAsServerAsync(_cert);
|
||||||
|
context.Connection = sslStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>5f64b3c3-0c2e-431a-b820-a81bbfc863da</ProjectGuid>
|
||||||
|
<RootNamespace>Microsoft.AspNet.Server.Kestrel.Https</RootNamespace>
|
||||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"description": "Adds HTTPS support to Kestrel",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/aspnet/kestrelhttpserver"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"dnx451": { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
public class ConnectionFilterContext
|
||||||
|
{
|
||||||
|
public ServerAddress Address { get; set; }
|
||||||
|
public Stream Connection { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
public class FilteredStreamAdapter
|
||||||
|
{
|
||||||
|
private readonly Stream _filteredStream;
|
||||||
|
private readonly Stream _socketInputStream;
|
||||||
|
private readonly IKestrelTrace _log;
|
||||||
|
|
||||||
|
public FilteredStreamAdapter(
|
||||||
|
Stream filteredStream,
|
||||||
|
MemoryPool2 memory,
|
||||||
|
IKestrelTrace logger)
|
||||||
|
{
|
||||||
|
SocketInput = new SocketInput(memory);
|
||||||
|
SocketOutput = new StreamSocketOutput(filteredStream);
|
||||||
|
|
||||||
|
_log = logger;
|
||||||
|
_filteredStream = filteredStream;
|
||||||
|
_socketInputStream = new SocketInputStream(SocketInput);
|
||||||
|
|
||||||
|
_filteredStream.CopyToAsync(_socketInputStream).ContinueWith((task, state) =>
|
||||||
|
{
|
||||||
|
((FilteredStreamAdapter)state).OnStreamClose(task);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketInput SocketInput { get; private set; }
|
||||||
|
|
||||||
|
public ISocketOutput SocketOutput { get; private set; }
|
||||||
|
|
||||||
|
private void OnStreamClose(Task copyAsyncTask)
|
||||||
|
{
|
||||||
|
if (copyAsyncTask.IsFaulted)
|
||||||
|
{
|
||||||
|
_log.LogError("FilteredStreamAdapter.CopyToAsync", copyAsyncTask.Exception);
|
||||||
|
}
|
||||||
|
else if (copyAsyncTask.IsCanceled)
|
||||||
|
{
|
||||||
|
_log.LogError("FilteredStreamAdapter.CopyToAsync canceled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_filteredStream.Dispose();
|
||||||
|
_socketInputStream.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.LogError("FilteredStreamAdapter.OnStreamClose", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
public interface IConnectionFilter
|
||||||
|
{
|
||||||
|
Task OnConnection(ConnectionFilterContext context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
public class LibuvStream : Stream
|
||||||
|
{
|
||||||
|
private readonly SocketInput _input;
|
||||||
|
private readonly ISocketOutput _output;
|
||||||
|
|
||||||
|
public LibuvStream(SocketInput input, ISocketOutput output)
|
||||||
|
{
|
||||||
|
_input = input;
|
||||||
|
_output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => true;
|
||||||
|
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return ReadAsync(new ArraySegment<byte>(buffer, offset, count)).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return ReadAsync(new ArraySegment<byte>(buffer, offset, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
var segment = new ArraySegment<byte>(buffer, offset, count);
|
||||||
|
_output.Write(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
|
||||||
|
{
|
||||||
|
var segment = new ArraySegment<byte>(buffer, offset, count);
|
||||||
|
return _output.WriteAsync(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
// No-op since writes are immediate.
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<int> ReadAsync(ArraySegment<byte> buffer)
|
||||||
|
{
|
||||||
|
return _input.ReadAsync(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
public class NoOpConnectionFilter : IConnectionFilter
|
||||||
|
{
|
||||||
|
private static Task _empty = Task.FromResult<object>(null);
|
||||||
|
|
||||||
|
public Task OnConnection(ConnectionFilterContext context)
|
||||||
|
{
|
||||||
|
return _empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is a write-only stream that copies what is written into a
|
||||||
|
/// <see cref="SocketInput"/> object. This is used as an argument to
|
||||||
|
/// <see cref="Stream.CopyToAsync(Stream)" /> so input filtered by a
|
||||||
|
/// ConnectionFilter (e.g. SslStream) can be consumed by <see cref="Frame"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class SocketInputStream : Stream
|
||||||
|
{
|
||||||
|
private static Task _emptyTask = Task.FromResult<object>(null);
|
||||||
|
private static byte[] _emptyBuffer = new byte[0];
|
||||||
|
|
||||||
|
private readonly SocketInput _socketInput;
|
||||||
|
|
||||||
|
public SocketInputStream(SocketInput socketInput)
|
||||||
|
{
|
||||||
|
_socketInput = socketInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => false;
|
||||||
|
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
var inputBuffer = _socketInput.IncomingStart(count);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(buffer, offset, inputBuffer.Data.Array, inputBuffer.Data.Offset, count);
|
||||||
|
|
||||||
|
_socketInput.IncomingComplete(count, error: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
|
||||||
|
{
|
||||||
|
Write(buffer, offset, count);
|
||||||
|
return _emptyTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
// Close _socketInput with a 0-length write.
|
||||||
|
Write(_emptyBuffer, 0, 0);
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Filter
|
||||||
|
{
|
||||||
|
public class StreamSocketOutput : ISocketOutput
|
||||||
|
{
|
||||||
|
private static readonly Task _emptyTask = Task.FromResult<object>(null);
|
||||||
|
|
||||||
|
private readonly Stream _outputStream;
|
||||||
|
|
||||||
|
public StreamSocketOutput(Stream outputStream)
|
||||||
|
{
|
||||||
|
_outputStream = outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISocketOutput.Write(ArraySegment<byte> buffer, bool immediate)
|
||||||
|
{
|
||||||
|
_outputStream.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ISocketOutput.WriteAsync(ArraySegment<byte> buffer, bool immediate, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Use _outputStream.WriteAsync
|
||||||
|
_outputStream.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||||
|
return _emptyTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Networking;
|
using Microsoft.AspNet.Server.Kestrel.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -18,9 +19,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
private static long _lastConnectionId;
|
private static long _lastConnectionId;
|
||||||
|
|
||||||
private readonly UvStreamHandle _socket;
|
private readonly UvStreamHandle _socket;
|
||||||
private readonly Frame _frame;
|
private Frame _frame;
|
||||||
|
private ConnectionFilterContext _filterContext;
|
||||||
private readonly long _connectionId;
|
private readonly long _connectionId;
|
||||||
|
|
||||||
|
private readonly SocketInput _rawSocketInput;
|
||||||
|
private readonly SocketOutput _rawSocketOutput;
|
||||||
|
|
||||||
private readonly object _stateLock = new object();
|
private readonly object _stateLock = new object();
|
||||||
private ConnectionState _connectionState;
|
private ConnectionState _connectionState;
|
||||||
|
|
||||||
|
|
@ -31,16 +36,67 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
_connectionId = Interlocked.Increment(ref _lastConnectionId);
|
_connectionId = Interlocked.Increment(ref _lastConnectionId);
|
||||||
|
|
||||||
SocketInput = new SocketInput(Memory2);
|
_rawSocketInput = new SocketInput(Memory2);
|
||||||
SocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log);
|
_rawSocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log);
|
||||||
_frame = new Frame(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
Log.ConnectionStart(_connectionId);
|
Log.ConnectionStart(_connectionId);
|
||||||
_frame.Start();
|
|
||||||
|
// Start socket prior to applying the ConnectionFilter
|
||||||
_socket.ReadStart(_allocCallback, _readCallback, this);
|
_socket.ReadStart(_allocCallback, _readCallback, this);
|
||||||
|
|
||||||
|
// Don't initialize _frame until SocketInput and SocketOutput are set to their final values.
|
||||||
|
if (ConnectionFilter == null)
|
||||||
|
{
|
||||||
|
SocketInput = _rawSocketInput;
|
||||||
|
SocketOutput = _rawSocketOutput;
|
||||||
|
|
||||||
|
_frame = new Frame(this);
|
||||||
|
_frame.Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var libuvStream = new LibuvStream(_rawSocketInput, _rawSocketOutput);
|
||||||
|
|
||||||
|
_filterContext = new ConnectionFilterContext
|
||||||
|
{
|
||||||
|
Connection = libuvStream,
|
||||||
|
Address = ServerAddress
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectionFilter.OnConnection(_filterContext).ContinueWith((task, state) =>
|
||||||
|
{
|
||||||
|
var connection = (Connection)state;
|
||||||
|
|
||||||
|
if (task.IsFaulted)
|
||||||
|
{
|
||||||
|
connection.Log.LogError("ConnectionFilter.OnConnection", task.Exception);
|
||||||
|
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
||||||
|
}
|
||||||
|
else if (task.IsCanceled)
|
||||||
|
{
|
||||||
|
connection.Log.LogError("ConnectionFilter.OnConnection Canceled");
|
||||||
|
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connection.ApplyConnectionFilter();
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyConnectionFilter()
|
||||||
|
{
|
||||||
|
var filteredStreamAdapter = new FilteredStreamAdapter(_filterContext.Connection, Memory2, Log);
|
||||||
|
|
||||||
|
SocketInput = filteredStreamAdapter.SocketInput;
|
||||||
|
SocketOutput = filteredStreamAdapter.SocketOutput;
|
||||||
|
|
||||||
|
_frame = new Frame(this);
|
||||||
|
_frame.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Libuv.uv_buf_t AllocCallback(UvStreamHandle handle, int suggestedSize, object state)
|
private static Libuv.uv_buf_t AllocCallback(UvStreamHandle handle, int suggestedSize, object state)
|
||||||
|
|
@ -50,7 +106,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
|
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
|
||||||
{
|
{
|
||||||
var result = SocketInput.IncomingStart(2048);
|
var result = _rawSocketInput.IncomingStart(2048);
|
||||||
|
|
||||||
return handle.Libuv.buf_init(
|
return handle.Libuv.buf_init(
|
||||||
result.DataPtr,
|
result.DataPtr,
|
||||||
|
|
@ -78,7 +134,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
Log.ConnectionReadFin(_connectionId);
|
Log.ConnectionReadFin(_connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketInput.IncomingComplete(readCount, errorDone ? error : null);
|
_rawSocketInput.IncomingComplete(readCount, errorDone ? error : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IConnectionControl.Pause()
|
void IConnectionControl.Pause()
|
||||||
|
|
@ -107,7 +163,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
_connectionState = ConnectionState.Shutdown;
|
_connectionState = ConnectionState.Shutdown;
|
||||||
|
|
||||||
Log.ConnectionWriteFin(_connectionId);
|
Log.ConnectionWriteFin(_connectionId);
|
||||||
SocketOutput.End(endType);
|
_rawSocketOutput.End(endType);
|
||||||
break;
|
break;
|
||||||
case ProduceEndType.ConnectionKeepAlive:
|
case ProduceEndType.ConnectionKeepAlive:
|
||||||
if (_connectionState != ConnectionState.Open)
|
if (_connectionState != ConnectionState.Open)
|
||||||
|
|
@ -125,7 +181,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
_connectionState = ConnectionState.Disconnected;
|
_connectionState = ConnectionState.Disconnected;
|
||||||
|
|
||||||
Log.ConnectionDisconnect(_connectionId);
|
Log.ConnectionDisconnect(_connectionId);
|
||||||
SocketOutput.End(endType);
|
_rawSocketOutput.End(endType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,5 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
void Write(ArraySegment<byte> buffer, bool immediate = true);
|
void Write(ArraySegment<byte> buffer, bool immediate = true);
|
||||||
Task WriteAsync(ArraySegment<byte> buffer, bool immediate = true, CancellationToken cancellationToken = default(CancellationToken));
|
Task WriteAsync(ArraySegment<byte> buffer, bool immediate = true, CancellationToken cancellationToken = default(CancellationToken));
|
||||||
void End(ProduceEndType endType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
protected UvStreamHandle ListenSocket { get; private set; }
|
protected UvStreamHandle ListenSocket { get; private set; }
|
||||||
|
|
||||||
public Task StartAsync(
|
public Task StartAsync(
|
||||||
string scheme,
|
ServerAddress address,
|
||||||
string host,
|
|
||||||
int port,
|
|
||||||
KestrelThread thread,
|
KestrelThread thread,
|
||||||
Func<Frame, Task> application)
|
Func<Frame, Task> application)
|
||||||
{
|
{
|
||||||
|
ServerAddress = address;
|
||||||
Thread = thread;
|
Thread = thread;
|
||||||
Application = application;
|
Application = application;
|
||||||
|
|
||||||
|
|
@ -35,7 +34,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ListenSocket = CreateListenSocket(host, port);
|
ListenSocket = CreateListenSocket();
|
||||||
tcs.SetResult(0);
|
tcs.SetResult(0);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -49,7 +48,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the socket used to listen for incoming connections
|
/// Creates the socket used to listen for incoming connections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract UvStreamHandle CreateListenSocket(string host, int port);
|
protected abstract UvStreamHandle CreateListenSocket();
|
||||||
|
|
||||||
protected static void ConnectionCallback(UvStreamHandle stream, int status, Exception error, object state)
|
protected static void ConnectionCallback(UvStreamHandle stream, int status, Exception error, object state)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
@ -23,13 +24,15 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
public ListenerContext(ListenerContext listenerContext)
|
public ListenerContext(ListenerContext listenerContext)
|
||||||
: base(listenerContext)
|
: base(listenerContext)
|
||||||
{
|
{
|
||||||
|
ServerAddress = listenerContext.ServerAddress;
|
||||||
Thread = listenerContext.Thread;
|
Thread = listenerContext.Thread;
|
||||||
Application = listenerContext.Application;
|
Application = listenerContext.Application;
|
||||||
Memory = listenerContext.Memory;
|
|
||||||
Memory2 = listenerContext.Memory2;
|
Memory2 = listenerContext.Memory2;
|
||||||
Log = listenerContext.Log;
|
Log = listenerContext.Log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ServerAddress ServerAddress { get; set; }
|
||||||
|
|
||||||
public KestrelThread Thread { get; set; }
|
public KestrelThread Thread { get; set; }
|
||||||
|
|
||||||
public Func<Frame, Task> Application { get; set; }
|
public Func<Frame, Task> Application { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public async Task StartAsync(
|
public async Task StartAsync(
|
||||||
string pipeName,
|
string pipeName,
|
||||||
string scheme,
|
ServerAddress address,
|
||||||
string host,
|
|
||||||
int port,
|
|
||||||
KestrelThread thread,
|
KestrelThread thread,
|
||||||
Func<Frame, Task> application)
|
Func<Frame, Task> application)
|
||||||
{
|
{
|
||||||
await StartAsync(scheme, host, port, thread, application).ConfigureAwait(false);
|
await StartAsync(address, thread, application).ConfigureAwait(false);
|
||||||
|
|
||||||
await Thread.PostAsync(_ =>
|
await Thread.PostAsync(_ =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public Task StartAsync(
|
public Task StartAsync(
|
||||||
string pipeName,
|
string pipeName,
|
||||||
|
ServerAddress address,
|
||||||
KestrelThread thread,
|
KestrelThread thread,
|
||||||
Func<Frame, Task> application)
|
Func<Frame, Task> application)
|
||||||
{
|
{
|
||||||
|
ServerAddress = address;
|
||||||
Thread = thread;
|
Thread = thread;
|
||||||
Application = application;
|
Application = application;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,27 +106,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken)
|
public override Task<int> ReadAsyncImplementation(ArraySegment<byte> buffer, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var input = _context.SocketInput;
|
return _context.SocketInput.ReadAsync(buffer);
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
await input;
|
|
||||||
|
|
||||||
var begin = input.ConsumingStart();
|
|
||||||
int actual;
|
|
||||||
var end = begin.CopyTo(buffer.Array, buffer.Offset, buffer.Count, out actual);
|
|
||||||
input.ConsumingComplete(end, end);
|
|
||||||
|
|
||||||
if (actual != 0)
|
|
||||||
{
|
|
||||||
return actual;
|
|
||||||
}
|
|
||||||
if (input.RemoteIntakeFin)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,30 +129,22 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
var input = _context.SocketInput;
|
var input = _context.SocketInput;
|
||||||
|
|
||||||
while (true)
|
var limit = Math.Min(buffer.Count, _inputLength);
|
||||||
|
if (limit == 0)
|
||||||
{
|
{
|
||||||
var limit = Math.Min(buffer.Count, _inputLength);
|
return 0;
|
||||||
if (limit == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
await input;
|
|
||||||
|
|
||||||
var begin = input.ConsumingStart();
|
|
||||||
int actual;
|
|
||||||
var end = begin.CopyTo(buffer.Array, buffer.Offset, limit, out actual);
|
|
||||||
_inputLength -= actual;
|
|
||||||
input.ConsumingComplete(end, end);
|
|
||||||
if (actual != 0)
|
|
||||||
{
|
|
||||||
return actual;
|
|
||||||
}
|
|
||||||
if (input.RemoteIntakeFin)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Unexpected end of request content");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var limitedBuffer = new ArraySegment<byte>(buffer.Array, buffer.Offset, limit);
|
||||||
|
var actual = await _context.SocketInput.ReadAsync(limitedBuffer);
|
||||||
|
_inputLength -= actual;
|
||||||
|
|
||||||
|
if (actual == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("Unexpected end of request content");
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the socket used to listen for incoming connections
|
/// Creates the socket used to listen for incoming connections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
protected override UvStreamHandle CreateListenSocket()
|
||||||
{
|
{
|
||||||
var socket = new UvPipeHandle(Log);
|
var socket = new UvPipeHandle(Log);
|
||||||
socket.Init(Thread.Loop, false);
|
socket.Init(Thread.Loop, false);
|
||||||
socket.Bind(host);
|
socket.Bind(ServerAddress.UnixPipePath);
|
||||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the socket used to listen for incoming connections
|
/// Creates the socket used to listen for incoming connections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
protected override UvStreamHandle CreateListenSocket()
|
||||||
{
|
{
|
||||||
var socket = new UvPipeHandle(Log);
|
var socket = new UvPipeHandle(Log);
|
||||||
socket.Init(Thread.Loop, false);
|
socket.Init(Thread.Loop, false);
|
||||||
socket.Bind(host);
|
socket.Bind(ServerAddress.UnixPipePath);
|
||||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
{
|
||||||
|
public static class SocketInputExtensions
|
||||||
|
{
|
||||||
|
public static async Task<int> ReadAsync(this SocketInput input, ArraySegment<byte> buffer)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
await input;
|
||||||
|
|
||||||
|
var begin = input.ConsumingStart();
|
||||||
|
int actual;
|
||||||
|
var end = begin.CopyTo(buffer.Array, buffer.Offset, buffer.Count, out actual);
|
||||||
|
input.ConsumingComplete(end, end);
|
||||||
|
|
||||||
|
if (actual != 0)
|
||||||
|
{
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
if (input.RemoteIntakeFin)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -114,6 +114,25 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void End(ProduceEndType endType)
|
||||||
|
{
|
||||||
|
switch (endType)
|
||||||
|
{
|
||||||
|
case ProduceEndType.SocketShutdownSend:
|
||||||
|
Write(default(ArraySegment<byte>), (error, state, calledInline) => { }, null,
|
||||||
|
immediate: true,
|
||||||
|
socketShutdownSend: true,
|
||||||
|
socketDisconnect: false);
|
||||||
|
break;
|
||||||
|
case ProduceEndType.SocketDisconnect:
|
||||||
|
Write(default(ArraySegment<byte>), (error, state, calledInline) => { }, null,
|
||||||
|
immediate: true,
|
||||||
|
socketShutdownSend: false,
|
||||||
|
socketDisconnect: true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ScheduleWrite()
|
private void ScheduleWrite()
|
||||||
{
|
{
|
||||||
_thread.Post(_this => _this.WriteAllPending(), this);
|
_thread.Post(_this => _this.WriteAllPending(), this);
|
||||||
|
|
@ -295,25 +314,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISocketOutput.End(ProduceEndType endType)
|
|
||||||
{
|
|
||||||
switch (endType)
|
|
||||||
{
|
|
||||||
case ProduceEndType.SocketShutdownSend:
|
|
||||||
Write(default(ArraySegment<byte>), (error, state, calledInline) => { }, null,
|
|
||||||
immediate: true,
|
|
||||||
socketShutdownSend: true,
|
|
||||||
socketDisconnect: false);
|
|
||||||
break;
|
|
||||||
case ProduceEndType.SocketDisconnect:
|
|
||||||
Write(default(ArraySegment<byte>), (error, state, calledInline) => { }, null,
|
|
||||||
immediate: true,
|
|
||||||
socketShutdownSend: false,
|
|
||||||
socketDisconnect: true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CallbackContext
|
private class CallbackContext
|
||||||
{
|
{
|
||||||
// callback(error, state, calledInline)
|
// callback(error, state, calledInline)
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the socket used to listen for incoming connections
|
/// Creates the socket used to listen for incoming connections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
protected override UvStreamHandle CreateListenSocket()
|
||||||
{
|
{
|
||||||
var socket = new UvTcpHandle(Log);
|
var socket = new UvTcpHandle(Log);
|
||||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||||
socket.Bind(host, port);
|
socket.Bind(ServerAddress);
|
||||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the socket used to listen for incoming connections
|
/// Creates the socket used to listen for incoming connections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
protected override UvStreamHandle CreateListenSocket()
|
||||||
{
|
{
|
||||||
var socket = new UvTcpHandle(Log);
|
var socket = new UvTcpHandle(Log);
|
||||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||||
socket.Bind(host, port);
|
socket.Bind(ServerAddress);
|
||||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
// 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.AspNet.Server.Kestrel.Filter;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.Kestrel
|
namespace Microsoft.AspNet.Server.Kestrel
|
||||||
{
|
{
|
||||||
public interface IKestrelServerInformation
|
public interface IKestrelServerInformation
|
||||||
{
|
{
|
||||||
int ThreadCount { get; set; }
|
int ThreadCount { get; set; }
|
||||||
|
|
||||||
|
IConnectionFilter ConnectionFilter { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,15 +98,11 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
Threads.Clear();
|
Threads.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDisposable CreateServer(string scheme, string host, int port, Func<Frame, Task> application)
|
public IDisposable CreateServer(ServerAddress address, Func<Frame, Task> application)
|
||||||
{
|
{
|
||||||
var listeners = new List<IDisposable>();
|
var listeners = new List<IDisposable>();
|
||||||
var usingPipes = host.StartsWith(Constants.UnixPipeHostPrefix);
|
|
||||||
if (usingPipes)
|
var usingPipes = address.IsUnixPipe;
|
||||||
{
|
|
||||||
// Subtract one because we want to include the '/' character that starts the path.
|
|
||||||
host = host.Substring(Constants.UnixPipeHostPrefix.Length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -123,7 +119,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
(Listener) new PipeListener(this) :
|
(Listener) new PipeListener(this) :
|
||||||
new TcpListener(this);
|
new TcpListener(this);
|
||||||
listeners.Add(listener);
|
listeners.Add(listener);
|
||||||
listener.StartAsync(scheme, host, port, thread, application).Wait();
|
listener.StartAsync(address, thread, application).Wait();
|
||||||
}
|
}
|
||||||
else if (first)
|
else if (first)
|
||||||
{
|
{
|
||||||
|
|
@ -132,7 +128,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
: new TcpListenerPrimary(this);
|
: new TcpListenerPrimary(this);
|
||||||
|
|
||||||
listeners.Add(listener);
|
listeners.Add(listener);
|
||||||
listener.StartAsync(pipeName, scheme, host, port, thread, application).Wait();
|
listener.StartAsync(pipeName, address, thread, application).Wait();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -140,7 +136,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
? (ListenerSecondary) new PipeListenerSecondary(this)
|
? (ListenerSecondary) new PipeListenerSecondary(this)
|
||||||
: new TcpListenerSecondary(this);
|
: new TcpListenerSecondary(this);
|
||||||
listeners.Add(listener);
|
listeners.Add(listener);
|
||||||
listener.StartAsync(pipeName, thread, application).Wait();
|
listener.StartAsync(pipeName, address, thread, application).Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.Server.Features;
|
using Microsoft.AspNet.Server.Features;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.Kestrel
|
namespace Microsoft.AspNet.Server.Kestrel
|
||||||
|
|
@ -14,6 +15,8 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
|
|
||||||
public int ThreadCount { get; set; }
|
public int ThreadCount { get; set; }
|
||||||
|
|
||||||
|
public IConnectionFilter ConnectionFilter { get; set; }
|
||||||
|
|
||||||
public void Initialize(IConfiguration configuration)
|
public void Initialize(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
var urls = configuration["server.urls"] ?? string.Empty;
|
var urls = configuration["server.urls"] ?? string.Empty;
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
_uv.tcp_init(loop, this);
|
_uv.tcp_init(loop, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind(string host, int port)
|
public void Bind(ServerAddress address)
|
||||||
{
|
{
|
||||||
var endpoint = CreateIPEndpoint(host, port);
|
var endpoint = CreateIPEndpoint(address);
|
||||||
|
|
||||||
Libuv.sockaddr addr;
|
Libuv.sockaddr addr;
|
||||||
var addressText = endpoint.Address.ToString();
|
var addressText = endpoint.Address.ToString();
|
||||||
|
|
@ -65,14 +65,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
/// Returns an <see cref="IPEndPoint"/> for the given host an port.
|
/// Returns an <see cref="IPEndPoint"/> for the given host an port.
|
||||||
/// If the host parameter isn't "localhost" or an IP address, use IPAddress.Any.
|
/// If the host parameter isn't "localhost" or an IP address, use IPAddress.Any.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IPEndPoint CreateIPEndpoint(string host, int port)
|
public static IPEndPoint CreateIPEndpoint(ServerAddress address)
|
||||||
{
|
{
|
||||||
// TODO: IPv6 support
|
// TODO: IPv6 support
|
||||||
IPAddress ip;
|
IPAddress ip;
|
||||||
|
|
||||||
if (!IPAddress.TryParse(host, out ip))
|
if (!IPAddress.TryParse(address.Host, out ip))
|
||||||
{
|
{
|
||||||
if (string.Equals(host, "localhost", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(address.Host, "localhost", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ip = IPAddress.Loopback;
|
ip = IPAddress.Loopback;
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IPEndPoint(ip, port);
|
return new IPEndPoint(ip, address.Port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||||
|
|
||||||
|
|
@ -14,6 +15,24 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
public int Port { get; private set; }
|
public int Port { get; private set; }
|
||||||
public string Scheme { get; private set; }
|
public string Scheme { get; private set; }
|
||||||
|
|
||||||
|
public bool IsUnixPipe
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Host.StartsWith(Constants.UnixPipeHostPrefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UnixPipePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Debug.Assert(IsUnixPipe);
|
||||||
|
|
||||||
|
return Host.Substring(Constants.UnixPipeHostPrefix.Length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant() + ":" + Port.ToString(CultureInfo.InvariantCulture) + Path.ToLowerInvariant();
|
return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant() + ":" + Port.ToString(CultureInfo.InvariantCulture) + Path.ToLowerInvariant();
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
{
|
{
|
||||||
AppShutdown = _appShutdownService,
|
AppShutdown = _appShutdownService,
|
||||||
Log = new KestrelTrace(_logger),
|
Log = new KestrelTrace(_logger),
|
||||||
DateHeaderValueManager = dateHeaderValueManager
|
DateHeaderValueManager = dateHeaderValueManager,
|
||||||
|
ConnectionFilter = information.ConnectionFilter
|
||||||
});
|
});
|
||||||
|
|
||||||
disposables.Push(engine);
|
disposables.Push(engine);
|
||||||
|
|
@ -86,9 +87,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
{
|
{
|
||||||
atLeastOneListener = true;
|
atLeastOneListener = true;
|
||||||
disposables.Push(engine.CreateServer(
|
disposables.Push(engine.CreateServer(
|
||||||
parsedAddress.Scheme,
|
parsedAddress,
|
||||||
parsedAddress.Host,
|
|
||||||
parsedAddress.Port,
|
|
||||||
async frame =>
|
async frame =>
|
||||||
{
|
{
|
||||||
var request = new ServerRequest(frame);
|
var request = new ServerRequest(frame);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +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.AspNet.Server.Kestrel.Filter;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Http;
|
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||||
using Microsoft.Dnx.Runtime;
|
using Microsoft.Dnx.Runtime;
|
||||||
|
|
@ -20,6 +21,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
Memory = context.Memory;
|
Memory = context.Memory;
|
||||||
Log = context.Log;
|
Log = context.Log;
|
||||||
DateHeaderValueManager = context.DateHeaderValueManager;
|
DateHeaderValueManager = context.DateHeaderValueManager;
|
||||||
|
ConnectionFilter = context.ConnectionFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IApplicationShutdown AppShutdown { get; set; }
|
public IApplicationShutdown AppShutdown { get; set; }
|
||||||
|
|
@ -29,5 +31,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
||||||
public IKestrelTrace Log { get; set; }
|
public IKestrelTrace Log { get; set; }
|
||||||
|
|
||||||
public DateHeaderValueManager DateHeaderValueManager { get; set; }
|
public DateHeaderValueManager DateHeaderValueManager { get; set; }
|
||||||
|
|
||||||
|
public IConnectionFilter ConnectionFilter { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel;
|
||||||
using Microsoft.AspNet.Server.Kestrel.Networking;
|
using Microsoft.AspNet.Server.Kestrel.Networking;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
public void CorrectIPEndpointsAreCreated(string host, string expectedAddress)
|
public void CorrectIPEndpointsAreCreated(string host, string expectedAddress)
|
||||||
{
|
{
|
||||||
// "0.0.0.0" is IPAddress.Any
|
// "0.0.0.0" is IPAddress.Any
|
||||||
var endpoint = UvTcpHandle.CreateIPEndpoint(host, 5000);
|
var endpoint = UvTcpHandle.CreateIPEndpoint(ServerAddress.FromUrl($"http://{host}:5000/"));
|
||||||
Assert.NotNull(endpoint);
|
Assert.NotNull(endpoint);
|
||||||
Assert.Equal(IPAddress.Parse(expectedAddress), endpoint.Address);
|
Assert.Equal(IPAddress.Parse(expectedAddress), endpoint.Address);
|
||||||
Assert.Equal(5000, endpoint.Port);
|
Assert.Equal(5000, endpoint.Port);
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
{
|
{
|
||||||
var engine = new KestrelEngine(LibraryManager, new TestServiceContext());
|
var engine = new KestrelEngine(LibraryManager, new TestServiceContext());
|
||||||
engine.Start(1);
|
engine.Start(1);
|
||||||
var started = engine.CreateServer("http", "localhost", 54321, App);
|
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||||
|
var started = engine.CreateServer(address, App);
|
||||||
started.Dispose();
|
started.Dispose();
|
||||||
engine.Dispose();
|
engine.Dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +100,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
{
|
{
|
||||||
var engine = new KestrelEngine(LibraryManager, new TestServiceContext());
|
var engine = new KestrelEngine(LibraryManager, new TestServiceContext());
|
||||||
engine.Start(1);
|
engine.Start(1);
|
||||||
var started = engine.CreateServer("http", "localhost", 54321, App);
|
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||||
|
var started = engine.CreateServer(address, App);
|
||||||
|
|
||||||
Console.WriteLine("Started");
|
Console.WriteLine("Started");
|
||||||
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
|
|
||||||
var serverListenTcp = new UvTcpHandle(_logger);
|
var serverListenTcp = new UvTcpHandle(_logger);
|
||||||
serverListenTcp.Init(loop);
|
serverListenTcp.Init(loop);
|
||||||
serverListenTcp.Bind("0.0.0.0", 54321);
|
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||||
|
serverListenTcp.Bind(address);
|
||||||
serverListenTcp.Listen(128, (_1, status, error, _2) =>
|
serverListenTcp.Listen(128, (_1, status, error, _2) =>
|
||||||
{
|
{
|
||||||
var serverConnectionTcp = new UvTcpHandle(_logger);
|
var serverConnectionTcp = new UvTcpHandle(_logger);
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
loop.Init(_uv);
|
loop.Init(_uv);
|
||||||
var tcp = new UvTcpHandle(_logger);
|
var tcp = new UvTcpHandle(_logger);
|
||||||
tcp.Init(loop);
|
tcp.Init(loop);
|
||||||
tcp.Bind("localhost", 0);
|
var address = ServerAddress.FromUrl("http://localhost:0/");
|
||||||
|
tcp.Bind(address);
|
||||||
tcp.Dispose();
|
tcp.Dispose();
|
||||||
loop.Run();
|
loop.Run();
|
||||||
loop.Dispose();
|
loop.Dispose();
|
||||||
|
|
@ -95,7 +96,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
loop.Init(_uv);
|
loop.Init(_uv);
|
||||||
var tcp = new UvTcpHandle(_logger);
|
var tcp = new UvTcpHandle(_logger);
|
||||||
tcp.Init(loop);
|
tcp.Init(loop);
|
||||||
tcp.Bind("localhost", 54321);
|
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||||
|
tcp.Bind(address);
|
||||||
tcp.Listen(10, (stream, status, error, state) =>
|
tcp.Listen(10, (stream, status, error, state) =>
|
||||||
{
|
{
|
||||||
var tcp2 = new UvTcpHandle(_logger);
|
var tcp2 = new UvTcpHandle(_logger);
|
||||||
|
|
@ -132,7 +134,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
loop.Init(_uv);
|
loop.Init(_uv);
|
||||||
var tcp = new UvTcpHandle(_logger);
|
var tcp = new UvTcpHandle(_logger);
|
||||||
tcp.Init(loop);
|
tcp.Init(loop);
|
||||||
tcp.Bind("localhost", 54321);
|
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||||
|
tcp.Bind(address);
|
||||||
tcp.Listen(10, (_, status, error, state) =>
|
tcp.Listen(10, (_, status, error, state) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("Connected");
|
Console.WriteLine("Connected");
|
||||||
|
|
@ -188,7 +191,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
loop.Init(_uv);
|
loop.Init(_uv);
|
||||||
var tcp = new UvTcpHandle(_logger);
|
var tcp = new UvTcpHandle(_logger);
|
||||||
tcp.Init(loop);
|
tcp.Init(loop);
|
||||||
tcp.Bind("localhost", 54321);
|
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||||
|
tcp.Bind(address);
|
||||||
tcp.Listen(10, (_, status, error, state) =>
|
tcp.Listen(10, (_, status, error, state) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("Connected");
|
Console.WriteLine("Connected");
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
kestrelEngine.Start(count: 1);
|
kestrelEngine.Start(count: 1);
|
||||||
|
|
||||||
var kestrelThread = kestrelEngine.Threads[0];
|
var kestrelThread = kestrelEngine.Threads[0];
|
||||||
var socket = new MockSocket(kestrelThread.Loop.ThreadId, new KestrelTrace(new TestKestrelTrace()));
|
var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
|
||||||
var trace = new KestrelTrace(new TestKestrelTrace());
|
var trace = new KestrelTrace(new TestKestrelTrace());
|
||||||
var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace);
|
var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace);
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
kestrelEngine.Start(count: 1);
|
kestrelEngine.Start(count: 1);
|
||||||
|
|
||||||
var kestrelThread = kestrelEngine.Threads[0];
|
var kestrelThread = kestrelEngine.Threads[0];
|
||||||
var socket = new MockSocket(kestrelThread.Loop.ThreadId, new KestrelTrace(new TestKestrelTrace()));
|
var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
|
||||||
var trace = new KestrelTrace(new TestKestrelTrace());
|
var trace = new KestrelTrace(new TestKestrelTrace());
|
||||||
var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace);
|
var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
new TestServiceContext());
|
new TestServiceContext());
|
||||||
_engine.Start(1);
|
_engine.Start(1);
|
||||||
_server = _engine.CreateServer(
|
_server = _engine.CreateServer(
|
||||||
"http",
|
ServerAddress.FromUrl("http://localhost:54321/"),
|
||||||
"localhost",
|
|
||||||
54321,
|
|
||||||
app);
|
app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue