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
|
||||
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
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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}.Release|Any CPU.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -79,5 +85,6 @@ Global
|
|||
{BD2D4D29-1BD9-40D0-BB31-337D5416B63C} = {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}
|
||||
{5F64B3C3-0C2E-431A-B820-A81BBFC863DA} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@
|
|||
"Microsoft.Extensions.Logging.Console": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Server.Kestrel.Https": "1.0.0-*"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"System.Console": "4.0.0-beta-*"
|
||||
|
|
@ -16,6 +20,6 @@
|
|||
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel",
|
||||
"run": "Microsoft.AspNet.Server.Kestrel",
|
||||
"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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||
using Microsoft.AspNet.Server.Kestrel.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -18,9 +19,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
private static long _lastConnectionId;
|
||||
|
||||
private readonly UvStreamHandle _socket;
|
||||
private readonly Frame _frame;
|
||||
private Frame _frame;
|
||||
private ConnectionFilterContext _filterContext;
|
||||
private readonly long _connectionId;
|
||||
|
||||
private readonly SocketInput _rawSocketInput;
|
||||
private readonly SocketOutput _rawSocketOutput;
|
||||
|
||||
private readonly object _stateLock = new object();
|
||||
private ConnectionState _connectionState;
|
||||
|
||||
|
|
@ -31,16 +36,67 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
_connectionId = Interlocked.Increment(ref _lastConnectionId);
|
||||
|
||||
SocketInput = new SocketInput(Memory2);
|
||||
SocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log);
|
||||
_frame = new Frame(this);
|
||||
_rawSocketInput = new SocketInput(Memory2);
|
||||
_rawSocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Log.ConnectionStart(_connectionId);
|
||||
_frame.Start();
|
||||
|
||||
// Start socket prior to applying the ConnectionFilter
|
||||
_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)
|
||||
|
|
@ -50,7 +106,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
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(
|
||||
result.DataPtr,
|
||||
|
|
@ -78,7 +134,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
Log.ConnectionReadFin(_connectionId);
|
||||
}
|
||||
|
||||
SocketInput.IncomingComplete(readCount, errorDone ? error : null);
|
||||
_rawSocketInput.IncomingComplete(readCount, errorDone ? error : null);
|
||||
}
|
||||
|
||||
void IConnectionControl.Pause()
|
||||
|
|
@ -107,7 +163,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
_connectionState = ConnectionState.Shutdown;
|
||||
|
||||
Log.ConnectionWriteFin(_connectionId);
|
||||
SocketOutput.End(endType);
|
||||
_rawSocketOutput.End(endType);
|
||||
break;
|
||||
case ProduceEndType.ConnectionKeepAlive:
|
||||
if (_connectionState != ConnectionState.Open)
|
||||
|
|
@ -125,7 +181,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
_connectionState = ConnectionState.Disconnected;
|
||||
|
||||
Log.ConnectionDisconnect(_connectionId);
|
||||
SocketOutput.End(endType);
|
||||
_rawSocketOutput.End(endType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,5 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
void Write(ArraySegment<byte> buffer, bool immediate = true);
|
||||
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; }
|
||||
|
||||
public Task StartAsync(
|
||||
string scheme,
|
||||
string host,
|
||||
int port,
|
||||
ServerAddress address,
|
||||
KestrelThread thread,
|
||||
Func<Frame, Task> application)
|
||||
{
|
||||
ServerAddress = address;
|
||||
Thread = thread;
|
||||
Application = application;
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
try
|
||||
{
|
||||
ListenSocket = CreateListenSocket(host, port);
|
||||
ListenSocket = CreateListenSocket();
|
||||
tcs.SetResult(0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -49,7 +48,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
/// <summary>
|
||||
/// Creates the socket used to listen for incoming connections
|
||||
/// </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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||
|
|
@ -23,13 +24,15 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
public ListenerContext(ListenerContext listenerContext)
|
||||
: base(listenerContext)
|
||||
{
|
||||
ServerAddress = listenerContext.ServerAddress;
|
||||
Thread = listenerContext.Thread;
|
||||
Application = listenerContext.Application;
|
||||
Memory = listenerContext.Memory;
|
||||
Memory2 = listenerContext.Memory2;
|
||||
Log = listenerContext.Log;
|
||||
}
|
||||
|
||||
public ServerAddress ServerAddress { get; set; }
|
||||
|
||||
public KestrelThread Thread { get; set; }
|
||||
|
||||
public Func<Frame, Task> Application { get; set; }
|
||||
|
|
|
|||
|
|
@ -31,13 +31,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
public async Task StartAsync(
|
||||
string pipeName,
|
||||
string scheme,
|
||||
string host,
|
||||
int port,
|
||||
ServerAddress address,
|
||||
KestrelThread thread,
|
||||
Func<Frame, Task> application)
|
||||
{
|
||||
await StartAsync(scheme, host, port, thread, application).ConfigureAwait(false);
|
||||
await StartAsync(address, thread, application).ConfigureAwait(false);
|
||||
|
||||
await Thread.PostAsync(_ =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,9 +24,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
public Task StartAsync(
|
||||
string pipeName,
|
||||
ServerAddress address,
|
||||
KestrelThread thread,
|
||||
Func<Frame, Task> application)
|
||||
{
|
||||
ServerAddress = address;
|
||||
Thread = thread;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
return _context.SocketInput.ReadAsync(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,30 +129,22 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
var input = _context.SocketInput;
|
||||
|
||||
while (true)
|
||||
var limit = Math.Min(buffer.Count, _inputLength);
|
||||
if (limit == 0)
|
||||
{
|
||||
var limit = Math.Min(buffer.Count, _inputLength);
|
||||
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");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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>
|
||||
/// Creates the socket used to listen for incoming connections
|
||||
/// </summary>
|
||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
||||
protected override UvStreamHandle CreateListenSocket()
|
||||
{
|
||||
var socket = new UvPipeHandle(Log);
|
||||
socket.Init(Thread.Loop, false);
|
||||
socket.Bind(host);
|
||||
socket.Bind(ServerAddress.UnixPipePath);
|
||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||
return socket;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
/// <summary>
|
||||
/// Creates the socket used to listen for incoming connections
|
||||
/// </summary>
|
||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
||||
protected override UvStreamHandle CreateListenSocket()
|
||||
{
|
||||
var socket = new UvPipeHandle(Log);
|
||||
socket.Init(Thread.Loop, false);
|
||||
socket.Bind(host);
|
||||
socket.Bind(ServerAddress.UnixPipePath);
|
||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||
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()
|
||||
{
|
||||
_thread.Post(_this => _this.WriteAllPending(), this);
|
||||
|
|
@ -295,25 +314,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
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
|
||||
{
|
||||
// callback(error, state, calledInline)
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
/// <summary>
|
||||
/// Creates the socket used to listen for incoming connections
|
||||
/// </summary>
|
||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
||||
protected override UvStreamHandle CreateListenSocket()
|
||||
{
|
||||
var socket = new UvTcpHandle(Log);
|
||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||
socket.Bind(host, port);
|
||||
socket.Bind(ServerAddress);
|
||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||
return socket;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
/// <summary>
|
||||
/// Creates the socket used to listen for incoming connections
|
||||
/// </summary>
|
||||
protected override UvStreamHandle CreateListenSocket(string host, int port)
|
||||
protected override UvStreamHandle CreateListenSocket()
|
||||
{
|
||||
var socket = new UvTcpHandle(Log);
|
||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||
socket.Bind(host, port);
|
||||
socket.Bind(ServerAddress);
|
||||
socket.Listen(Constants.ListenBacklog, ConnectionCallback, this);
|
||||
return socket;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
// 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.AspNet.Server.Kestrel.Filter;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel
|
||||
{
|
||||
public interface IKestrelServerInformation
|
||||
{
|
||||
int ThreadCount { get; set; }
|
||||
|
||||
IConnectionFilter ConnectionFilter { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,15 +98,11 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
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 usingPipes = host.StartsWith(Constants.UnixPipeHostPrefix);
|
||||
if (usingPipes)
|
||||
{
|
||||
// Subtract one because we want to include the '/' character that starts the path.
|
||||
host = host.Substring(Constants.UnixPipeHostPrefix.Length - 1);
|
||||
}
|
||||
|
||||
var usingPipes = address.IsUnixPipe;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -123,7 +119,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
(Listener) new PipeListener(this) :
|
||||
new TcpListener(this);
|
||||
listeners.Add(listener);
|
||||
listener.StartAsync(scheme, host, port, thread, application).Wait();
|
||||
listener.StartAsync(address, thread, application).Wait();
|
||||
}
|
||||
else if (first)
|
||||
{
|
||||
|
|
@ -132,7 +128,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
: new TcpListenerPrimary(this);
|
||||
|
||||
listeners.Add(listener);
|
||||
listener.StartAsync(pipeName, scheme, host, port, thread, application).Wait();
|
||||
listener.StartAsync(pipeName, address, thread, application).Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -140,7 +136,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
? (ListenerSecondary) new PipeListenerSecondary(this)
|
||||
: new TcpListenerSecondary(this);
|
||||
listeners.Add(listener);
|
||||
listener.StartAsync(pipeName, thread, application).Wait();
|
||||
listener.StartAsync(pipeName, address, thread, application).Wait();
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Server.Features;
|
||||
using Microsoft.AspNet.Server.Kestrel.Filter;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel
|
||||
|
|
@ -14,6 +15,8 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
|
||||
public int ThreadCount { get; set; }
|
||||
|
||||
public IConnectionFilter ConnectionFilter { get; set; }
|
||||
|
||||
public void Initialize(IConfiguration configuration)
|
||||
{
|
||||
var urls = configuration["server.urls"] ?? string.Empty;
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
|
|||
_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;
|
||||
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.
|
||||
/// If the host parameter isn't "localhost" or an IP address, use IPAddress.Any.
|
||||
/// </summary>
|
||||
public static IPEndPoint CreateIPEndpoint(string host, int port)
|
||||
public static IPEndPoint CreateIPEndpoint(ServerAddress address)
|
||||
{
|
||||
// TODO: IPv6 support
|
||||
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;
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||
|
||||
|
|
@ -14,6 +15,24 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
public int Port { 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()
|
||||
{
|
||||
return Scheme.ToLowerInvariant() + "://" + Host.ToLowerInvariant() + ":" + Port.ToString(CultureInfo.InvariantCulture) + Path.ToLowerInvariant();
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
AppShutdown = _appShutdownService,
|
||||
Log = new KestrelTrace(_logger),
|
||||
DateHeaderValueManager = dateHeaderValueManager
|
||||
DateHeaderValueManager = dateHeaderValueManager,
|
||||
ConnectionFilter = information.ConnectionFilter
|
||||
});
|
||||
|
||||
disposables.Push(engine);
|
||||
|
|
@ -86,9 +87,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
atLeastOneListener = true;
|
||||
disposables.Push(engine.CreateServer(
|
||||
parsedAddress.Scheme,
|
||||
parsedAddress.Host,
|
||||
parsedAddress.Port,
|
||||
parsedAddress,
|
||||
async frame =>
|
||||
{
|
||||
var request = new ServerRequest(frame);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.AspNet.Server.Kestrel.Filter;
|
||||
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||
using Microsoft.Dnx.Runtime;
|
||||
|
|
@ -20,6 +21,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
Memory = context.Memory;
|
||||
Log = context.Log;
|
||||
DateHeaderValueManager = context.DateHeaderValueManager;
|
||||
ConnectionFilter = context.ConnectionFilter;
|
||||
}
|
||||
|
||||
public IApplicationShutdown AppShutdown { get; set; }
|
||||
|
|
@ -29,5 +31,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
public IKestrelTrace Log { 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.
|
||||
|
||||
using System.Net;
|
||||
using Microsoft.AspNet.Server.Kestrel;
|
||||
using Microsoft.AspNet.Server.Kestrel.Networking;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
public void CorrectIPEndpointsAreCreated(string host, string expectedAddress)
|
||||
{
|
||||
// "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.Equal(IPAddress.Parse(expectedAddress), endpoint.Address);
|
||||
Assert.Equal(5000, endpoint.Port);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
{
|
||||
var engine = new KestrelEngine(LibraryManager, new TestServiceContext());
|
||||
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();
|
||||
engine.Dispose();
|
||||
}
|
||||
|
|
@ -99,7 +100,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
{
|
||||
var engine = new KestrelEngine(LibraryManager, new TestServiceContext());
|
||||
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");
|
||||
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
|
|
|||
|
|
@ -166,7 +166,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
|
||||
var serverListenTcp = new UvTcpHandle(_logger);
|
||||
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) =>
|
||||
{
|
||||
var serverConnectionTcp = new UvTcpHandle(_logger);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
loop.Init(_uv);
|
||||
var tcp = new UvTcpHandle(_logger);
|
||||
tcp.Init(loop);
|
||||
tcp.Bind("localhost", 0);
|
||||
var address = ServerAddress.FromUrl("http://localhost:0/");
|
||||
tcp.Bind(address);
|
||||
tcp.Dispose();
|
||||
loop.Run();
|
||||
loop.Dispose();
|
||||
|
|
@ -95,7 +96,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
loop.Init(_uv);
|
||||
var tcp = new UvTcpHandle(_logger);
|
||||
tcp.Init(loop);
|
||||
tcp.Bind("localhost", 54321);
|
||||
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||
tcp.Bind(address);
|
||||
tcp.Listen(10, (stream, status, error, state) =>
|
||||
{
|
||||
var tcp2 = new UvTcpHandle(_logger);
|
||||
|
|
@ -132,7 +134,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
loop.Init(_uv);
|
||||
var tcp = new UvTcpHandle(_logger);
|
||||
tcp.Init(loop);
|
||||
tcp.Bind("localhost", 54321);
|
||||
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||
tcp.Bind(address);
|
||||
tcp.Listen(10, (_, status, error, state) =>
|
||||
{
|
||||
Console.WriteLine("Connected");
|
||||
|
|
@ -188,7 +191,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
loop.Init(_uv);
|
||||
var tcp = new UvTcpHandle(_logger);
|
||||
tcp.Init(loop);
|
||||
tcp.Bind("localhost", 54321);
|
||||
var address = ServerAddress.FromUrl("http://localhost:54321/");
|
||||
tcp.Bind(address);
|
||||
tcp.Listen(10, (_, status, error, state) =>
|
||||
{
|
||||
Console.WriteLine("Connected");
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
kestrelEngine.Start(count: 1);
|
||||
|
||||
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 socketOutput = new SocketOutput(kestrelThread, socket, 0, trace);
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
kestrelEngine.Start(count: 1);
|
||||
|
||||
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 socketOutput = new SocketOutput(kestrelThread, socket, 0, trace);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,9 +52,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
new TestServiceContext());
|
||||
_engine.Start(1);
|
||||
_server = _engine.CreateServer(
|
||||
"http",
|
||||
"localhost",
|
||||
54321,
|
||||
ServerAddress.FromUrl("http://localhost:54321/"),
|
||||
app);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue