Expose DefaultConnectionContext POCO (#2421)

- Made TransportConnecton derive from ConnectionContext
- Less objects, less opinions about what the ConnectionContext is. This diverges from what we do with HttpContext but it seems better overall.
- Made DefaultConnectionContext
 - Usable for unit testing
 - Usable for benchmarking
This commit is contained in:
David Fowler 2018-03-24 03:12:53 -07:00 committed by GitHub
parent 63fd1e1a4d
commit 6701339835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 42 deletions

View File

@ -3,11 +3,12 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal namespace Microsoft.AspNetCore.Connections
{ {
internal class ConnectionItems : IDictionary<object, object> public class ConnectionItems : IDictionary<object, object>
{ {
public ConnectionItems() public ConnectionItems()
: this(new Dictionary<object, object>()) : this(new Dictionary<object, object>())
@ -115,4 +116,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
return Items.GetEnumerator(); return Items.GetEnumerator();
} }
} }
} }

View File

@ -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.IO.Pipelines;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Connections.Features;
namespace Microsoft.AspNetCore.Connections namespace Microsoft.AspNetCore.Connections
{ {
public class DefaultConnectionContext : ConnectionContext public class DefaultConnectionContext : ConnectionContext,
IConnectionIdFeature,
IConnectionItemsFeature,
IConnectionTransportFeature,
IApplicationTransportFeature,
IConnectionUserFeature
{ {
private FeatureReferences<FeatureInterfaces> _features; public DefaultConnectionContext() :
this(Guid.NewGuid().ToString())
public DefaultConnectionContext(IFeatureCollection features)
{ {
_features = new FeatureReferences<FeatureInterfaces>(features);
} }
private IConnectionIdFeature ConnectionIdFeature => /// <summary>
_features.Fetch(ref _features.Cache.ConnectionId, _ => null); /// Creates the DefaultConnectionContext without Pipes to avoid upfront allocations.
/// The caller is expected to set the <see cref="Transport"/> and <see cref="Application"/> pipes manually.
private IConnectionTransportFeature ConnectionTransportFeature => /// </summary>
_features.Fetch(ref _features.Cache.ConnectionTransport, _ => null); /// <param name="id"></param>
public DefaultConnectionContext(string id)
private IConnectionItemsFeature ConnectionItemsFeature =>
_features.Fetch(ref _features.Cache.ConnectionItems, _ => null);
public override string ConnectionId
{ {
get => ConnectionIdFeature.ConnectionId; ConnectionId = id;
set => ConnectionIdFeature.ConnectionId = value;
Features = new FeatureCollection();
Features.Set<IConnectionUserFeature>(this);
Features.Set<IConnectionItemsFeature>(this);
Features.Set<IConnectionIdFeature>(this);
Features.Set<IConnectionTransportFeature>(this);
Features.Set<IApplicationTransportFeature>(this);
} }
public override IFeatureCollection Features => _features.Collection; public DefaultConnectionContext(string id, IDuplexPipe transport, IDuplexPipe application)
: this(id)
public override IDuplexPipe Transport
{ {
get => ConnectionTransportFeature.Transport; Transport = transport;
set => ConnectionTransportFeature.Transport = value; Application = application;
} }
public override IDictionary<object, object> Items public override string ConnectionId { get; set; }
{
get => ConnectionItemsFeature.Items;
set => ConnectionItemsFeature.Items = value;
}
struct FeatureInterfaces public override IFeatureCollection Features { get; }
{
public IConnectionIdFeature ConnectionId;
public IConnectionTransportFeature ConnectionTransport; public ClaimsPrincipal User { get; set; }
public IConnectionItemsFeature ConnectionItems; public override IDictionary<object, object> Items { get; set; } = new ConnectionItems();
}
public IDuplexPipe Application { get; set; }
public override IDuplexPipe Transport { get; set; }
} }
} }

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
// REVIEW: This task should be tracked by the server for graceful shutdown // REVIEW: This task should be tracked by the server for graceful shutdown
// Today it's handled specifically for http but not for aribitrary middleware // Today it's handled specifically for http but not for aribitrary middleware
_ = Execute(new DefaultConnectionContext(connection)); _ = Execute(connection);
} }
private async Task Execute(ConnectionContext connectionContext) private async Task Execute(ConnectionContext connectionContext)

View File

@ -3,10 +3,12 @@ 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 Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
public abstract partial class TransportConnection public abstract partial class TransportConnection : ConnectionContext
{ {
private IDictionary<object, object> _items; private IDictionary<object, object> _items;
@ -26,16 +28,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
public IPAddress LocalAddress { get; set; } public IPAddress LocalAddress { get; set; }
public int LocalPort { 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<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; }
public IDuplexPipe Transport { get; set; } public override IDuplexPipe Transport { get; set; }
public IDuplexPipe Application { get; set; } public IDuplexPipe Application { get; set; }
public IDictionary<object, object> Items public override IDictionary<object, object> Items
{ {
get get
{ {