diff --git a/src/Kestrel.Transport.Abstractions/Internal/ConnectionItems.cs b/src/Connections.Abstractions/ConnectionItems.cs similarity index 95% rename from src/Kestrel.Transport.Abstractions/Internal/ConnectionItems.cs rename to src/Connections.Abstractions/ConnectionItems.cs index adb346df81..0f01a62111 100644 --- a/src/Kestrel.Transport.Abstractions/Internal/ConnectionItems.cs +++ b/src/Connections.Abstractions/ConnectionItems.cs @@ -3,11 +3,12 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; -namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal +namespace Microsoft.AspNetCore.Connections { - internal class ConnectionItems : IDictionary + public class ConnectionItems : IDictionary { public ConnectionItems() : this(new Dictionary()) @@ -115,4 +116,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal return Items.GetEnumerator(); } } -} \ No newline at end of file +} diff --git a/src/Connections.Abstractions/DefaultConnectionContext.cs b/src/Connections.Abstractions/DefaultConnectionContext.cs index 920efba18b..33607c0a5c 100644 --- a/src/Connections.Abstractions/DefaultConnectionContext.cs +++ b/src/Connections.Abstractions/DefaultConnectionContext.cs @@ -1,55 +1,64 @@ -using System.Collections.Generic; +// 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.Collections.Generic; using System.IO.Pipelines; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections.Features; namespace Microsoft.AspNetCore.Connections { - public class DefaultConnectionContext : ConnectionContext + public class DefaultConnectionContext : ConnectionContext, + IConnectionIdFeature, + IConnectionItemsFeature, + IConnectionTransportFeature, + IApplicationTransportFeature, + IConnectionUserFeature { - private FeatureReferences _features; - - public DefaultConnectionContext(IFeatureCollection features) + public DefaultConnectionContext() : + this(Guid.NewGuid().ToString()) { - _features = new FeatureReferences(features); } - private IConnectionIdFeature ConnectionIdFeature => - _features.Fetch(ref _features.Cache.ConnectionId, _ => null); - - private IConnectionTransportFeature ConnectionTransportFeature => - _features.Fetch(ref _features.Cache.ConnectionTransport, _ => null); - - private IConnectionItemsFeature ConnectionItemsFeature => - _features.Fetch(ref _features.Cache.ConnectionItems, _ => null); - - public override string ConnectionId + /// + /// Creates the DefaultConnectionContext without Pipes to avoid upfront allocations. + /// The caller is expected to set the and pipes manually. + /// + /// + public DefaultConnectionContext(string id) { - get => ConnectionIdFeature.ConnectionId; - set => ConnectionIdFeature.ConnectionId = value; + ConnectionId = id; + + Features = new FeatureCollection(); + Features.Set(this); + Features.Set(this); + Features.Set(this); + Features.Set(this); + Features.Set(this); } - public override IFeatureCollection Features => _features.Collection; - - public override IDuplexPipe Transport + public DefaultConnectionContext(string id, IDuplexPipe transport, IDuplexPipe application) + : this(id) { - get => ConnectionTransportFeature.Transport; - set => ConnectionTransportFeature.Transport = value; + Transport = transport; + Application = application; } - public override IDictionary Items - { - get => ConnectionItemsFeature.Items; - set => ConnectionItemsFeature.Items = value; - } + public override string ConnectionId { get; set; } - struct FeatureInterfaces - { - public IConnectionIdFeature ConnectionId; + public override IFeatureCollection Features { get; } - public IConnectionTransportFeature ConnectionTransport; + public ClaimsPrincipal User { get; set; } - public IConnectionItemsFeature ConnectionItems; - } + public override IDictionary Items { get; set; } = new ConnectionItems(); + + public IDuplexPipe Application { get; set; } + + public override IDuplexPipe Transport { get; set; } } } diff --git a/src/Kestrel.Core/Internal/ConnectionListener.cs b/src/Kestrel.Core/Internal/ConnectionListener.cs index d3daa84158..abbbe6b50d 100644 --- a/src/Kestrel.Core/Internal/ConnectionListener.cs +++ b/src/Kestrel.Core/Internal/ConnectionListener.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal // REVIEW: This task should be tracked by the server for graceful shutdown // Today it's handled specifically for http but not for aribitrary middleware - _ = Execute(new DefaultConnectionContext(connection)); + _ = Execute(connection); } private async Task Execute(ConnectionContext connectionContext) diff --git a/src/Kestrel.Transport.Abstractions/Internal/TransportConnection.cs b/src/Kestrel.Transport.Abstractions/Internal/TransportConnection.cs index b753dae64a..c3d014ea57 100644 --- a/src/Kestrel.Transport.Abstractions/Internal/TransportConnection.cs +++ b/src/Kestrel.Transport.Abstractions/Internal/TransportConnection.cs @@ -3,10 +3,12 @@ using System.Collections.Generic; using System.IO.Pipelines; using System.Net; using System.Threading; +using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal { - public abstract partial class TransportConnection + public abstract partial class TransportConnection : ConnectionContext { private IDictionary _items; @@ -26,16 +28,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal public IPAddress LocalAddress { get; set; } public int LocalPort { get; set; } - public string ConnectionId { get; set; } + public override string ConnectionId { get; set; } + + public override IFeatureCollection Features => this; public virtual MemoryPool MemoryPool { get; } public virtual PipeScheduler InputWriterScheduler { get; } public virtual PipeScheduler OutputReaderScheduler { get; } - public IDuplexPipe Transport { get; set; } + public override IDuplexPipe Transport { get; set; } public IDuplexPipe Application { get; set; } - public IDictionary Items + public override IDictionary Items { get {