Add IConnectionCompleteFeature.OnCompleted #9213 (#9754)

This commit is contained in:
Chris Ross 2019-04-29 18:34:31 -07:00 committed by GitHub
parent 868b012cda
commit 9579a6fe17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 199 additions and 6 deletions

View File

@ -100,6 +100,10 @@ namespace Microsoft.AspNetCore.Connections
} }
namespace Microsoft.AspNetCore.Connections.Features namespace Microsoft.AspNetCore.Connections.Features
{ {
public partial interface IConnectionCompleteFeature
{
void OnCompleted(System.Func<object, System.Threading.Tasks.Task> callback, object state);
}
public partial interface IConnectionHeartbeatFeature public partial interface IConnectionHeartbeatFeature
{ {
void OnHeartbeat(System.Action<object> action, object state); void OnHeartbeat(System.Action<object> action, object state);

View File

@ -0,0 +1,22 @@
// 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.AspNetCore.Connections.Features
{
/// <summary>
/// Represents the completion action for a connection.
/// </summary>
public interface IConnectionCompleteFeature
{
/// <summary>
/// Registers a callback to be invoked after a connection has fully completed processing. This is
/// intended for resource cleanup.
/// </summary>
/// <param name="callback">The callback to invoke after the connection has completed processing.</param>
/// <param name="state">The state to pass into the callback.</param>
void OnCompleted(Func<object, Task> callback, object state);
}
}

View File

@ -82,6 +82,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
finally finally
{ {
await connectionContext.CompleteAsync();
Log.ConnectionStop(connectionContext.ConnectionId); Log.ConnectionStop(connectionContext.ConnectionId);
KestrelEventSource.Log.ConnectionStop(connectionContext); KestrelEventSource.Log.ConnectionStop(connectionContext);

View File

@ -7,9 +7,11 @@ using System.IO.Pipelines;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Xunit; using Xunit;
@ -69,5 +71,50 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
mockPipeWriter.Verify(m => m.Complete(It.IsAny<Exception>()), Times.Once()); mockPipeWriter.Verify(m => m.Complete(It.IsAny<Exception>()), Times.Once());
mockPipeReader.Verify(m => m.Complete(It.IsAny<Exception>()), Times.Once()); mockPipeReader.Verify(m => m.Complete(It.IsAny<Exception>()), Times.Once());
} }
[Fact]
public async Task OnConnectionFiresOnCompleted()
{
var serviceContext = new TestServiceContext();
var dispatcher = new ConnectionDispatcher(serviceContext, _ => Task.CompletedTask);
var connection = new Mock<TransportConnection> { CallBase = true }.Object;
connection.ConnectionClosed = new CancellationToken(canceled: true);
var completeFeature = connection.Features.Get<IConnectionCompleteFeature>();
Assert.NotNull(completeFeature);
object stateObject = new object();
object callbackState = null;
completeFeature.OnCompleted(state => { callbackState = state; return Task.CompletedTask; }, stateObject);
await dispatcher.OnConnection(connection);
Assert.Equal(stateObject, callbackState);
}
[Fact]
public async Task OnConnectionOnCompletedExceptionCaught()
{
var serviceContext = new TestServiceContext();
var dispatcher = new ConnectionDispatcher(serviceContext, _ => Task.CompletedTask);
var connection = new Mock<TransportConnection> { CallBase = true }.Object;
connection.ConnectionClosed = new CancellationToken(canceled: true);
var completeFeature = connection.Features.Get<IConnectionCompleteFeature>();
var mockLogger = new Mock<ILogger>();
connection.Logger = mockLogger.Object;
Assert.NotNull(completeFeature);
object stateObject = new object();
object callbackState = null;
completeFeature.OnCompleted(state => { callbackState = state; throw new InvalidTimeZoneException(); }, stateObject);
await dispatcher.OnConnection(connection);
Assert.Equal(stateObject, callbackState);
var log = mockLogger.Invocations.First();
Assert.Equal("An error occured running an IConnectionCompleteFeature.OnCompleted callback.", log.Arguments[2].ToString());
Assert.IsType<InvalidTimeZoneException>(log.Arguments[3]);
}
} }
} }

View File

@ -6,5 +6,6 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
<Compile Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.netcoreapp3.0.cs" /> <Compile Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions" /> <Reference Include="Microsoft.AspNetCore.Connections.Abstractions" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
ThreadPool = 1, ThreadPool = 1,
Inline = 2, Inline = 2,
} }
public abstract partial class TransportConnection : Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Features.IConnectionHeartbeatFeature, Microsoft.AspNetCore.Connections.Features.IConnectionIdFeature, Microsoft.AspNetCore.Connections.Features.IConnectionItemsFeature, Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature, Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeNotificationFeature, Microsoft.AspNetCore.Connections.Features.IConnectionTransportFeature, Microsoft.AspNetCore.Connections.Features.IMemoryPoolFeature, Microsoft.AspNetCore.Http.Features.IFeatureCollection, Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature, Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.IApplicationTransportFeature, Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.ITransportSchedulerFeature, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<System.Type, object>>, System.Collections.IEnumerable public abstract partial class TransportConnection : Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Features.IConnectionCompleteFeature, Microsoft.AspNetCore.Connections.Features.IConnectionHeartbeatFeature, Microsoft.AspNetCore.Connections.Features.IConnectionIdFeature, Microsoft.AspNetCore.Connections.Features.IConnectionItemsFeature, Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature, Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeNotificationFeature, Microsoft.AspNetCore.Connections.Features.IConnectionTransportFeature, Microsoft.AspNetCore.Connections.Features.IMemoryPoolFeature, Microsoft.AspNetCore.Http.Features.IFeatureCollection, Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature, Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.IApplicationTransportFeature, Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.ITransportSchedulerFeature, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<System.Type, object>>, System.Collections.IEnumerable
{ {
protected readonly System.Threading.CancellationTokenSource _connectionClosingCts; protected readonly System.Threading.CancellationTokenSource _connectionClosingCts;
public TransportConnection() { } public TransportConnection() { }
@ -73,6 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
public override System.Collections.Generic.IDictionary<object, object> Items { get { throw null; } set { } } public override System.Collections.Generic.IDictionary<object, object> Items { get { throw null; } set { } }
public System.Net.IPAddress LocalAddress { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public System.Net.IPAddress LocalAddress { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public int LocalPort { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public int LocalPort { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
protected internal virtual Microsoft.Extensions.Logging.ILogger Logger { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public virtual System.Buffers.MemoryPool<byte> MemoryPool { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public virtual System.Buffers.MemoryPool<byte> MemoryPool { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
System.Collections.Generic.IDictionary<object, object> Microsoft.AspNetCore.Connections.Features.IConnectionItemsFeature.Items { get { throw null; } set { } } System.Collections.Generic.IDictionary<object, object> Microsoft.AspNetCore.Connections.Features.IConnectionItemsFeature.Items { get { throw null; } set { } }
System.Threading.CancellationToken Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature.ConnectionClosed { get { throw null; } set { } } System.Threading.CancellationToken Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature.ConnectionClosed { get { throw null; } set { } }
@ -96,6 +97,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
public int RemotePort { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public int RemotePort { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public override System.IO.Pipelines.IDuplexPipe Transport { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public override System.IO.Pipelines.IDuplexPipe Transport { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public override void Abort(Microsoft.AspNetCore.Connections.ConnectionAbortedException abortReason) { } public override void Abort(Microsoft.AspNetCore.Connections.ConnectionAbortedException abortReason) { }
public System.Threading.Tasks.Task CompleteAsync() { throw null; }
void Microsoft.AspNetCore.Connections.Features.IConnectionCompleteFeature.OnCompleted(System.Func<object, System.Threading.Tasks.Task> callback, object state) { }
void Microsoft.AspNetCore.Connections.Features.IConnectionHeartbeatFeature.OnHeartbeat(System.Action<object> action, object state) { } void Microsoft.AspNetCore.Connections.Features.IConnectionHeartbeatFeature.OnHeartbeat(System.Action<object> action, object state) { }
void Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature.Abort() { } void Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature.Abort() { }
void Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeNotificationFeature.RequestClose() { } void Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeNotificationFeature.RequestClose() { }

View File

@ -1,14 +1,17 @@
// 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 System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
@ -21,12 +24,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
ITransportSchedulerFeature, ITransportSchedulerFeature,
IConnectionLifetimeFeature, IConnectionLifetimeFeature,
IConnectionHeartbeatFeature, IConnectionHeartbeatFeature,
IConnectionLifetimeNotificationFeature IConnectionLifetimeNotificationFeature,
IConnectionCompleteFeature
{ {
// NOTE: When feature interfaces are added to or removed from this TransportConnection class implementation, // NOTE: When feature interfaces are added to or removed from this TransportConnection class implementation,
// then the list of `features` in the generated code project MUST also be updated. // then the list of `features` in the generated code project MUST also be updated.
// See also: tools/CodeGenerator/TransportConnectionFeatureCollection.cs // See also: tools/CodeGenerator/TransportConnectionFeatureCollection.cs
private Stack<KeyValuePair<Func<object, Task>, object>> _onCompleted;
private bool _completed;
string IHttpConnectionFeature.ConnectionId string IHttpConnectionFeature.ConnectionId
{ {
get => ConnectionId; get => ConnectionId;
@ -100,5 +107,82 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
OnHeartbeat(action, state); OnHeartbeat(action, state);
} }
void IConnectionCompleteFeature.OnCompleted(Func<object, Task> callback, object state)
{
if (_completed)
{
throw new InvalidOperationException("The connection is already complete.");
}
if (_onCompleted == null)
{
_onCompleted = new Stack<KeyValuePair<Func<object, Task>, object>>();
}
_onCompleted.Push(new KeyValuePair<Func<object, Task>, object>(callback, state));
}
public Task CompleteAsync()
{
if (_completed)
{
throw new InvalidOperationException("The connection is already complete.");
}
_completed = true;
var onCompleted = _onCompleted;
if (onCompleted == null || onCompleted.Count == 0)
{
return Task.CompletedTask;
}
return CompleteAsyncMayAwait(onCompleted);
}
private Task CompleteAsyncMayAwait(Stack<KeyValuePair<Func<object, Task>, object>> onCompleted)
{
while (onCompleted.TryPop(out var entry))
{
try
{
var task = entry.Key.Invoke(entry.Value);
if (!ReferenceEquals(task, Task.CompletedTask))
{
return CompleteAsyncAwaited(task, onCompleted);
}
}
catch (Exception ex)
{
Logger?.LogError(ex, "An error occured running an IConnectionCompleteFeature.OnCompleted callback.");
}
}
return Task.CompletedTask;
}
private async Task CompleteAsyncAwaited(Task currentTask, Stack<KeyValuePair<Func<object, Task>, object>> onCompleted)
{
try
{
await currentTask;
}
catch (Exception ex)
{
Logger?.LogError(ex, "An error occured running an IConnectionCompleteFeature.OnCompleted callback.");
}
while (onCompleted.TryPop(out var entry))
{
try
{
await entry.Key.Invoke(entry.Value);
}
catch (Exception ex)
{
Logger?.LogError(ex, "An error occured running an IConnectionCompleteFeature.OnCompleted callback.");
}
}
}
} }
} }

View File

@ -22,6 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
private static readonly Type IConnectionLifetimeFeatureType = typeof(IConnectionLifetimeFeature); private static readonly Type IConnectionLifetimeFeatureType = typeof(IConnectionLifetimeFeature);
private static readonly Type IConnectionHeartbeatFeatureType = typeof(IConnectionHeartbeatFeature); private static readonly Type IConnectionHeartbeatFeatureType = typeof(IConnectionHeartbeatFeature);
private static readonly Type IConnectionLifetimeNotificationFeatureType = typeof(IConnectionLifetimeNotificationFeature); private static readonly Type IConnectionLifetimeNotificationFeatureType = typeof(IConnectionLifetimeNotificationFeature);
private static readonly Type IConnectionCompleteFeatureType = typeof(IConnectionCompleteFeature);
private object _currentIHttpConnectionFeature; private object _currentIHttpConnectionFeature;
private object _currentIConnectionIdFeature; private object _currentIConnectionIdFeature;
@ -33,6 +34,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
private object _currentIConnectionLifetimeFeature; private object _currentIConnectionLifetimeFeature;
private object _currentIConnectionHeartbeatFeature; private object _currentIConnectionHeartbeatFeature;
private object _currentIConnectionLifetimeNotificationFeature; private object _currentIConnectionLifetimeNotificationFeature;
private object _currentIConnectionCompleteFeature;
private int _featureRevision; private int _featureRevision;
@ -50,6 +52,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
_currentIConnectionLifetimeFeature = this; _currentIConnectionLifetimeFeature = this;
_currentIConnectionHeartbeatFeature = this; _currentIConnectionHeartbeatFeature = this;
_currentIConnectionLifetimeNotificationFeature = this; _currentIConnectionLifetimeNotificationFeature = this;
_currentIConnectionCompleteFeature = this;
} }
@ -145,6 +148,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
feature = _currentIConnectionLifetimeNotificationFeature; feature = _currentIConnectionLifetimeNotificationFeature;
} }
else if (key == IConnectionCompleteFeatureType)
{
feature = _currentIConnectionCompleteFeature;
}
else if (MaybeExtra != null) else if (MaybeExtra != null)
{ {
feature = ExtraFeatureGet(key); feature = ExtraFeatureGet(key);
@ -197,6 +204,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
_currentIConnectionLifetimeNotificationFeature = value; _currentIConnectionLifetimeNotificationFeature = value;
} }
else if (key == IConnectionCompleteFeatureType)
{
_currentIConnectionCompleteFeature = value;
}
else else
{ {
ExtraFeatureSet(key, value); ExtraFeatureSet(key, value);
@ -247,6 +258,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
feature = (TFeature)_currentIConnectionLifetimeNotificationFeature; feature = (TFeature)_currentIConnectionLifetimeNotificationFeature;
} }
else if (typeof(TFeature) == typeof(IConnectionCompleteFeature))
{
feature = (TFeature)_currentIConnectionCompleteFeature;
}
else if (MaybeExtra != null) else if (MaybeExtra != null)
{ {
feature = (TFeature)(ExtraFeatureGet(typeof(TFeature))); feature = (TFeature)(ExtraFeatureGet(typeof(TFeature)));
@ -298,6 +313,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
_currentIConnectionLifetimeNotificationFeature = feature; _currentIConnectionLifetimeNotificationFeature = feature;
} }
else if (typeof(TFeature) == typeof(IConnectionCompleteFeature))
{
_currentIConnectionCompleteFeature = feature;
}
else else
{ {
ExtraFeatureSet(typeof(TFeature), feature); ExtraFeatureSet(typeof(TFeature), feature);
@ -346,6 +365,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
yield return new KeyValuePair<Type, object>(IConnectionLifetimeNotificationFeatureType, _currentIConnectionLifetimeNotificationFeature); yield return new KeyValuePair<Type, object>(IConnectionLifetimeNotificationFeatureType, _currentIConnectionLifetimeNotificationFeature);
} }
if (_currentIConnectionCompleteFeature != null)
{
yield return new KeyValuePair<Type, object>(IConnectionCompleteFeatureType, _currentIConnectionCompleteFeature);
}
if (MaybeExtra != null) if (MaybeExtra != null)
{ {

View File

@ -1,4 +1,4 @@
// 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 System; using System;
@ -9,6 +9,7 @@ using System.Net;
using System.Threading; using System.Threading;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
@ -35,6 +36,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
public override IFeatureCollection Features => this; public override IFeatureCollection Features => this;
protected internal virtual ILogger Logger { get; set; }
public virtual MemoryPool<byte> MemoryPool { get; } public virtual MemoryPool<byte> MemoryPool { get; }
public virtual PipeScheduler InputWriterScheduler { get; } public virtual PipeScheduler InputWriterScheduler { get; }
public virtual PipeScheduler OutputReaderScheduler { get; } public virtual PipeScheduler OutputReaderScheduler { get; }

View File

@ -17,6 +17,7 @@
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions" /> <Reference Include="Microsoft.AspNetCore.Connections.Abstractions" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -43,6 +43,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
LocalPort = localEndPoint?.Port ?? 0; LocalPort = localEndPoint?.Port ?? 0;
ConnectionClosed = _connectionClosedTokenSource.Token; ConnectionClosed = _connectionClosedTokenSource.Token;
Logger = log;
Log = log; Log = log;
Thread = thread; Thread = thread;
} }

View File

@ -42,6 +42,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
_socket = socket; _socket = socket;
MemoryPool = memoryPool; MemoryPool = memoryPool;
_scheduler = scheduler; _scheduler = scheduler;
Logger = trace;
_trace = trace; _trace = trace;
var localEndPoint = (IPEndPoint)_socket.LocalEndPoint; var localEndPoint = (IPEndPoint)_socket.LocalEndPoint;

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace CodeGenerator namespace CodeGenerator
@ -20,7 +20,8 @@ namespace CodeGenerator
"ITransportSchedulerFeature", "ITransportSchedulerFeature",
"IConnectionLifetimeFeature", "IConnectionLifetimeFeature",
"IConnectionHeartbeatFeature", "IConnectionHeartbeatFeature",
"IConnectionLifetimeNotificationFeature" "IConnectionLifetimeNotificationFeature",
"IConnectionCompleteFeature"
}; };
var usings = $@" var usings = $@"