Progress towards deleting Sockets.Abstractions (#1705)
* Progress towards deleting Sockets.Abstractions - Moved our custom DefaultConnectionContext to Sockets.Http and renamed it to HttpConnectionContext. - Renamed ConnectionManager to HttpConnectionManager - Use DefaultConnection in tests and benchmarks - Delete ConnectionMetadata
This commit is contained in:
parent
a9667c3fbd
commit
cb05ce4e0b
|
|
@ -4,6 +4,7 @@ using System.Threading;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal;
|
using Microsoft.AspNetCore.SignalR.Internal;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
||||||
using Microsoft.AspNetCore.Sockets;
|
using Microsoft.AspNetCore.Sockets;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
new Logger<DefaultHubDispatcher<TestHub>>(NullLoggerFactory.Instance));
|
new Logger<DefaultHubDispatcher<TestHub>>(NullLoggerFactory.Instance));
|
||||||
|
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new Sockets.DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
|
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
|
||||||
|
|
||||||
_connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);
|
_connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@
|
||||||
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreHttpPackageVersion>
|
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreHttpPackageVersion>
|
||||||
<MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>
|
<MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreIdentityEntityFrameworkCorePackageVersion>
|
||||||
<MicrosoftAspNetCoreMvcPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreMvcPackageVersion>
|
<MicrosoftAspNetCoreMvcPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreMvcPackageVersion>
|
||||||
<MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>2.1.0-a-preview2-bedrock-renames-17598</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>
|
<MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>2.1.0-a-preview2-default-connection-context-17612</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreRoutingPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreRoutingPackageVersion>
|
<MicrosoftAspNetCoreRoutingPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreRoutingPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.0-preview2-30355</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
|
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.0-preview2-30355</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.0-a-preview2-bedrock-renames-17598</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.0-a-preview2-default-connection-context-17612</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||||
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
||||||
<MicrosoftAspNetCoreTestHostPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreTestHostPackageVersion>
|
<MicrosoftAspNetCoreTestHostPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreTestHostPackageVersion>
|
||||||
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreTestingPackageVersion>
|
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview2-30355</MicrosoftAspNetCoreTestingPackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
// 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;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets
|
|
||||||
{
|
|
||||||
internal class ConnectionMetadata : IDictionary<object, object>
|
|
||||||
{
|
|
||||||
public ConnectionMetadata()
|
|
||||||
: this(new ConcurrentDictionary<object, object>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConnectionMetadata(IDictionary<object, object> items)
|
|
||||||
{
|
|
||||||
Items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDictionary<object, object> Items { get; }
|
|
||||||
|
|
||||||
// Replace the indexer with one that returns null for missing values
|
|
||||||
object IDictionary<object, object>.this[object key]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Items.TryGetValue(key, out var value))
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
set { Items[key] = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDictionary<object, object>.Add(object key, object value)
|
|
||||||
{
|
|
||||||
Items.Add(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IDictionary<object, object>.ContainsKey(object key)
|
|
||||||
{
|
|
||||||
return Items.ContainsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
ICollection<object> IDictionary<object, object>.Keys
|
|
||||||
{
|
|
||||||
get { return Items.Keys; }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IDictionary<object, object>.Remove(object key)
|
|
||||||
{
|
|
||||||
return Items.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IDictionary<object, object>.TryGetValue(object key, out object value)
|
|
||||||
{
|
|
||||||
return Items.TryGetValue(key, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ICollection<object> IDictionary<object, object>.Values
|
|
||||||
{
|
|
||||||
get { return Items.Values; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICollection<KeyValuePair<object, object>>.Add(KeyValuePair<object, object> item)
|
|
||||||
{
|
|
||||||
Items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICollection<KeyValuePair<object, object>>.Clear()
|
|
||||||
{
|
|
||||||
Items.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<object, object>>.Contains(KeyValuePair<object, object> item)
|
|
||||||
{
|
|
||||||
return Items.Contains(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICollection<KeyValuePair<object, object>>.CopyTo(KeyValuePair<object, object>[] array, int arrayIndex)
|
|
||||||
{
|
|
||||||
Items.CopyTo(array, arrayIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ICollection<KeyValuePair<object, object>>.Count
|
|
||||||
{
|
|
||||||
get { return Items.Count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<object, object>>.IsReadOnly
|
|
||||||
{
|
|
||||||
get { return Items.IsReadOnly; }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<object, object>>.Remove(KeyValuePair<object, object> item)
|
|
||||||
{
|
|
||||||
object value;
|
|
||||||
if (Items.TryGetValue(item.Key, out value) && Equals(item.Value, value))
|
|
||||||
{
|
|
||||||
return Items.Remove(item.Key);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator<KeyValuePair<object, object>> IEnumerable<KeyValuePair<object, object>>.GetEnumerator()
|
|
||||||
{
|
|
||||||
return Items.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return Items.GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,5 +5,7 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<RootNamespace>Microsoft.AspNetCore.Sockets</RootNamespace>
|
<RootNamespace>Microsoft.AspNetCore.Sockets</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="$(MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.AddRouting();
|
services.AddRouting();
|
||||||
services.AddAuthorizationPolicyEvaluator();
|
services.AddAuthorizationPolicyEvaluator();
|
||||||
services.TryAddSingleton<HttpConnectionDispatcher>();
|
services.TryAddSingleton<HttpConnectionDispatcher>();
|
||||||
services.TryAddSingleton<ConnectionManager>();
|
services.TryAddSingleton<HttpConnectionManager>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
@ -10,17 +11,20 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
using Microsoft.AspNetCore.Connections.Features;
|
using Microsoft.AspNetCore.Connections.Features;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets
|
namespace Microsoft.AspNetCore.Sockets
|
||||||
{
|
{
|
||||||
public class DefaultConnectionContext : ConnectionContext,
|
public class HttpConnectionContext : ConnectionContext,
|
||||||
IConnectionIdFeature,
|
IConnectionIdFeature,
|
||||||
IConnectionItemsFeature,
|
IConnectionItemsFeature,
|
||||||
IConnectionTransportFeature,
|
IConnectionTransportFeature,
|
||||||
IApplicationTransportFeature,
|
IApplicationTransportFeature,
|
||||||
IConnectionUserFeature,
|
IConnectionUserFeature,
|
||||||
IConnectionHeartbeatFeature,
|
IConnectionHeartbeatFeature,
|
||||||
ITransferFormatFeature
|
ITransferFormatFeature,
|
||||||
|
IHttpContextFeature
|
||||||
{
|
{
|
||||||
private object _heartbeatLock = new object();
|
private object _heartbeatLock = new object();
|
||||||
private List<(Action<object> handler, object state)> _heartbeatHandlers;
|
private List<(Action<object> handler, object state)> _heartbeatHandlers;
|
||||||
|
|
@ -34,7 +38,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
/// The caller is expected to set the <see cref="Transport"/> and <see cref="Application"/> pipes manually.
|
/// The caller is expected to set the <see cref="Transport"/> and <see cref="Application"/> pipes manually.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
public DefaultConnectionContext(string id)
|
public HttpConnectionContext(string id)
|
||||||
{
|
{
|
||||||
ConnectionId = id;
|
ConnectionId = id;
|
||||||
LastSeenUtc = DateTime.UtcNow;
|
LastSeenUtc = DateTime.UtcNow;
|
||||||
|
|
@ -52,9 +56,10 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
Features.Set<IApplicationTransportFeature>(this);
|
Features.Set<IApplicationTransportFeature>(this);
|
||||||
Features.Set<IConnectionHeartbeatFeature>(this);
|
Features.Set<IConnectionHeartbeatFeature>(this);
|
||||||
Features.Set<ITransferFormatFeature>(this);
|
Features.Set<ITransferFormatFeature>(this);
|
||||||
|
Features.Set<IHttpContextFeature>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultConnectionContext(string id, IDuplexPipe transport, IDuplexPipe application)
|
public HttpConnectionContext(string id, IDuplexPipe transport, IDuplexPipe application)
|
||||||
: this(id)
|
: this(id)
|
||||||
{
|
{
|
||||||
Transport = transport;
|
Transport = transport;
|
||||||
|
|
@ -79,7 +84,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
|
|
||||||
public ClaimsPrincipal User { get; set; }
|
public ClaimsPrincipal User { get; set; }
|
||||||
|
|
||||||
public override IDictionary<object, object> Items { get; set; } = new ConnectionMetadata();
|
public override IDictionary<object, object> Items { get; set; } = new ConnectionItems(new ConcurrentDictionary<object, object>());
|
||||||
|
|
||||||
public IDuplexPipe Application { get; set; }
|
public IDuplexPipe Application { get; set; }
|
||||||
|
|
||||||
|
|
@ -89,6 +94,8 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
|
|
||||||
public TransferFormat ActiveFormat { get; set; }
|
public TransferFormat ActiveFormat { get; set; }
|
||||||
|
|
||||||
|
public HttpContext HttpContext { get; set; }
|
||||||
|
|
||||||
public void OnHeartbeat(Action<object> action, object state)
|
public void OnHeartbeat(Action<object> action, object state)
|
||||||
{
|
{
|
||||||
lock (_heartbeatLock)
|
lock (_heartbeatLock)
|
||||||
|
|
@ -24,11 +24,11 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
{
|
{
|
||||||
public partial class HttpConnectionDispatcher
|
public partial class HttpConnectionDispatcher
|
||||||
{
|
{
|
||||||
private readonly ConnectionManager _manager;
|
private readonly HttpConnectionManager _manager;
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public HttpConnectionDispatcher(ConnectionManager manager, ILoggerFactory loggerFactory)
|
public HttpConnectionDispatcher(HttpConnectionManager manager, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
|
|
@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
{
|
{
|
||||||
await connection.Lock.WaitAsync();
|
await connection.Lock.WaitAsync();
|
||||||
|
|
||||||
if (connection.Status == DefaultConnectionContext.ConnectionStatus.Disposed)
|
if (connection.Status == HttpConnectionContext.ConnectionStatus.Disposed)
|
||||||
{
|
{
|
||||||
Log.ConnectionDisposed(_logger, connection.ConnectionId);
|
Log.ConnectionDisposed(_logger, connection.ConnectionId);
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection.Status == DefaultConnectionContext.ConnectionStatus.Active)
|
if (connection.Status == HttpConnectionContext.ConnectionStatus.Active)
|
||||||
{
|
{
|
||||||
var existing = connection.GetHttpContext();
|
var existing = connection.GetHttpContext();
|
||||||
Log.ConnectionAlreadyActive(_logger, connection.ConnectionId, existing.TraceIdentifier);
|
Log.ConnectionAlreadyActive(_logger, connection.ConnectionId, existing.TraceIdentifier);
|
||||||
|
|
@ -196,7 +196,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the connection as active
|
// Mark the connection as active
|
||||||
connection.Status = DefaultConnectionContext.ConnectionStatus.Active;
|
connection.Status = HttpConnectionContext.ConnectionStatus.Active;
|
||||||
|
|
||||||
// Raise OnConnected for new connections only since polls happen all the time
|
// Raise OnConnected for new connections only since polls happen all the time
|
||||||
if (connection.ApplicationTask == null)
|
if (connection.ApplicationTask == null)
|
||||||
|
|
@ -271,12 +271,12 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
{
|
{
|
||||||
await connection.Lock.WaitAsync();
|
await connection.Lock.WaitAsync();
|
||||||
|
|
||||||
if (connection.Status == DefaultConnectionContext.ConnectionStatus.Active)
|
if (connection.Status == HttpConnectionContext.ConnectionStatus.Active)
|
||||||
{
|
{
|
||||||
// Mark the connection as inactive
|
// Mark the connection as inactive
|
||||||
connection.LastSeenUtc = DateTime.UtcNow;
|
connection.LastSeenUtc = DateTime.UtcNow;
|
||||||
|
|
||||||
connection.Status = DefaultConnectionContext.ConnectionStatus.Inactive;
|
connection.Status = HttpConnectionContext.ConnectionStatus.Inactive;
|
||||||
|
|
||||||
// Dispose the cancellation token
|
// Dispose the cancellation token
|
||||||
connection.Cancellation.Dispose();
|
connection.Cancellation.Dispose();
|
||||||
|
|
@ -295,13 +295,13 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
private async Task DoPersistentConnection(ConnectionDelegate connectionDelegate,
|
private async Task DoPersistentConnection(ConnectionDelegate connectionDelegate,
|
||||||
IHttpTransport transport,
|
IHttpTransport transport,
|
||||||
HttpContext context,
|
HttpContext context,
|
||||||
DefaultConnectionContext connection)
|
HttpConnectionContext connection)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await connection.Lock.WaitAsync();
|
await connection.Lock.WaitAsync();
|
||||||
|
|
||||||
if (connection.Status == DefaultConnectionContext.ConnectionStatus.Disposed)
|
if (connection.Status == HttpConnectionContext.ConnectionStatus.Disposed)
|
||||||
{
|
{
|
||||||
Log.ConnectionDisposed(_logger, connection.ConnectionId);
|
Log.ConnectionDisposed(_logger, connection.ConnectionId);
|
||||||
|
|
||||||
|
|
@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
|
|
||||||
// There's already an active request
|
// There's already an active request
|
||||||
if (connection.Status == DefaultConnectionContext.ConnectionStatus.Active)
|
if (connection.Status == HttpConnectionContext.ConnectionStatus.Active)
|
||||||
{
|
{
|
||||||
Log.ConnectionAlreadyActive(_logger, connection.ConnectionId, connection.GetHttpContext().TraceIdentifier);
|
Log.ConnectionAlreadyActive(_logger, connection.ConnectionId, connection.GetHttpContext().TraceIdentifier);
|
||||||
|
|
||||||
|
|
@ -321,7 +321,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the connection as active
|
// Mark the connection as active
|
||||||
connection.Status = DefaultConnectionContext.ConnectionStatus.Active;
|
connection.Status = HttpConnectionContext.ConnectionStatus.Active;
|
||||||
|
|
||||||
// Call into the end point passing the connection
|
// Call into the end point passing the connection
|
||||||
connection.ApplicationTask = ExecuteApplication(connectionDelegate, connection);
|
connection.ApplicationTask = ExecuteApplication(connectionDelegate, connection);
|
||||||
|
|
@ -471,7 +471,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
await connection.Application.Output.FlushAsync();
|
await connection.Application.Output.FlushAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> EnsureConnectionStateAsync(DefaultConnectionContext connection, HttpContext context, TransportType transportType, TransportType supportedTransports, ConnectionLogScope logScope, HttpConnectionOptions options)
|
private async Task<bool> EnsureConnectionStateAsync(HttpConnectionContext connection, HttpContext context, TransportType transportType, TransportType supportedTransports, ConnectionLogScope logScope, HttpConnectionOptions options)
|
||||||
{
|
{
|
||||||
if ((supportedTransports & transportType) == 0)
|
if ((supportedTransports & transportType) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -512,11 +512,11 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
// To make the IHttpContextFeature work well, we make a copy of the relevant properties
|
// To make the IHttpContextFeature work well, we make a copy of the relevant properties
|
||||||
// to a new HttpContext. This means that it's impossible to affect the context
|
// to a new HttpContext. This means that it's impossible to affect the context
|
||||||
// with subsequent requests.
|
// with subsequent requests.
|
||||||
var existing = connection.GetHttpContext();
|
var existing = connection.HttpContext;
|
||||||
if (existing == null)
|
if (existing == null)
|
||||||
{
|
{
|
||||||
var httpContext = CloneHttpContext(context);
|
var httpContext = CloneHttpContext(context);
|
||||||
connection.SetHttpContext(httpContext);
|
connection.HttpContext = httpContext;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -527,7 +527,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connection.SetHttpContext(context);
|
connection.HttpContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the Connection ID on the logging scope so that logs from now on will have the
|
// Set the Connection ID on the logging scope so that logs from now on will have the
|
||||||
|
|
@ -596,7 +596,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
return newHttpContext;
|
return newHttpContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<DefaultConnectionContext> GetConnectionAsync(HttpContext context, HttpConnectionOptions options)
|
private async Task<HttpConnectionContext> GetConnectionAsync(HttpContext context, HttpConnectionOptions options)
|
||||||
{
|
{
|
||||||
var connectionId = GetConnectionId(context);
|
var connectionId = GetConnectionId(context);
|
||||||
|
|
||||||
|
|
@ -623,7 +623,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureConnectionStateInternal(DefaultConnectionContext connection, HttpConnectionOptions options)
|
private void EnsureConnectionStateInternal(HttpConnectionContext connection, HttpConnectionOptions options)
|
||||||
{
|
{
|
||||||
// If the connection doesn't have a pipe yet then create one, we lazily create the pipe to save on allocations until the client actually connects
|
// If the connection doesn't have a pipe yet then create one, we lazily create the pipe to save on allocations until the client actually connects
|
||||||
if (connection.Transport == null)
|
if (connection.Transport == null)
|
||||||
|
|
@ -637,10 +637,10 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only used for WebSockets connections, which can connect directly without negotiating
|
// This is only used for WebSockets connections, which can connect directly without negotiating
|
||||||
private async Task<DefaultConnectionContext> GetOrCreateConnectionAsync(HttpContext context, HttpConnectionOptions options)
|
private async Task<HttpConnectionContext> GetOrCreateConnectionAsync(HttpContext context, HttpConnectionOptions options)
|
||||||
{
|
{
|
||||||
var connectionId = GetConnectionId(context);
|
var connectionId = GetConnectionId(context);
|
||||||
DefaultConnectionContext connection;
|
HttpConnectionContext connection;
|
||||||
|
|
||||||
// There's no connection id so this is a brand new connection
|
// There's no connection id so this is a brand new connection
|
||||||
if (StringValues.IsNullOrEmpty(connectionId))
|
if (StringValues.IsNullOrEmpty(connectionId))
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,20 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets
|
namespace Microsoft.AspNetCore.Sockets
|
||||||
{
|
{
|
||||||
public class ConnectionManager
|
public class HttpConnectionManager
|
||||||
{
|
{
|
||||||
// TODO: Consider making this configurable? At least for testing?
|
// TODO: Consider making this configurable? At least for testing?
|
||||||
private static readonly TimeSpan _heartbeatTickRate = TimeSpan.FromSeconds(1);
|
private static readonly TimeSpan _heartbeatTickRate = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
private static readonly RNGCryptoServiceProvider _keyGenerator = new RNGCryptoServiceProvider();
|
private static readonly RNGCryptoServiceProvider _keyGenerator = new RNGCryptoServiceProvider();
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, (DefaultConnectionContext Connection, ValueStopwatch Timer)> _connections = new ConcurrentDictionary<string, (DefaultConnectionContext Connection, ValueStopwatch Timer)>();
|
private readonly ConcurrentDictionary<string, (HttpConnectionContext Connection, ValueStopwatch Timer)> _connections = new ConcurrentDictionary<string, (HttpConnectionContext Connection, ValueStopwatch Timer)>();
|
||||||
private Timer _timer;
|
private Timer _timer;
|
||||||
private readonly ILogger<ConnectionManager> _logger;
|
private readonly ILogger<HttpConnectionManager> _logger;
|
||||||
private object _executionLock = new object();
|
private object _executionLock = new object();
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public ConnectionManager(ILogger<ConnectionManager> logger, IApplicationLifetime appLifetime)
|
public HttpConnectionManager(ILogger<HttpConnectionManager> logger, IApplicationLifetime appLifetime)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
appLifetime.ApplicationStarted.Register(() => Start());
|
appLifetime.ApplicationStarted.Register(() => Start());
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetConnection(string id, out DefaultConnectionContext connection)
|
public bool TryGetConnection(string id, out HttpConnectionContext connection)
|
||||||
{
|
{
|
||||||
connection = null;
|
connection = null;
|
||||||
|
|
||||||
|
|
@ -71,20 +71,20 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
/// Creates a connection without Pipes setup to allow saving allocations until Pipes are needed.
|
/// Creates a connection without Pipes setup to allow saving allocations until Pipes are needed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public DefaultConnectionContext CreateConnection()
|
public HttpConnectionContext CreateConnection()
|
||||||
{
|
{
|
||||||
var id = MakeNewConnectionId();
|
var id = MakeNewConnectionId();
|
||||||
|
|
||||||
_logger.CreatedNewConnection(id);
|
_logger.CreatedNewConnection(id);
|
||||||
var connectionTimer = SocketEventSource.Log.ConnectionStart(id);
|
var connectionTimer = SocketEventSource.Log.ConnectionStart(id);
|
||||||
|
|
||||||
var connection = new DefaultConnectionContext(id);
|
var connection = new HttpConnectionContext(id);
|
||||||
|
|
||||||
_connections.TryAdd(id, (connection, connectionTimer));
|
_connections.TryAdd(id, (connection, connectionTimer));
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultConnectionContext CreateConnection(PipeOptions transportPipeOptions, PipeOptions appPipeOptions)
|
public HttpConnectionContext CreateConnection(PipeOptions transportPipeOptions, PipeOptions appPipeOptions)
|
||||||
{
|
{
|
||||||
var connection = CreateConnection();
|
var connection = CreateConnection();
|
||||||
var pair = DuplexPipe.CreateConnectionPair(transportPipeOptions, appPipeOptions);
|
var pair = DuplexPipe.CreateConnectionPair(transportPipeOptions, appPipeOptions);
|
||||||
|
|
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
|
|
||||||
private static void Scan(object state)
|
private static void Scan(object state)
|
||||||
{
|
{
|
||||||
((ConnectionManager)state).Scan();
|
((HttpConnectionManager)state).Scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Scan()
|
public void Scan()
|
||||||
|
|
@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
// Scan the registered connections looking for ones that have timed out
|
// Scan the registered connections looking for ones that have timed out
|
||||||
foreach (var c in _connections)
|
foreach (var c in _connections)
|
||||||
{
|
{
|
||||||
var status = DefaultConnectionContext.ConnectionStatus.Inactive;
|
var status = HttpConnectionContext.ConnectionStatus.Inactive;
|
||||||
var lastSeenUtc = DateTimeOffset.UtcNow;
|
var lastSeenUtc = DateTimeOffset.UtcNow;
|
||||||
var connection = c.Value.Connection;
|
var connection = c.Value.Connection;
|
||||||
|
|
||||||
|
|
@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
|
|
||||||
// Once the decision has been made to dispose we don't check the status again
|
// Once the decision has been made to dispose we don't check the status again
|
||||||
// But don't clean up connections while the debugger is attached.
|
// But don't clean up connections while the debugger is attached.
|
||||||
if (!Debugger.IsAttached && status == DefaultConnectionContext.ConnectionStatus.Inactive && (DateTimeOffset.UtcNow - lastSeenUtc).TotalSeconds > 5)
|
if (!Debugger.IsAttached && status == HttpConnectionContext.ConnectionStatus.Inactive && (DateTimeOffset.UtcNow - lastSeenUtc).TotalSeconds > 5)
|
||||||
{
|
{
|
||||||
_logger.ConnectionTimedOut(connection.ConnectionId);
|
_logger.ConnectionTimedOut(connection.ConnectionId);
|
||||||
SocketEventSource.Log.ConnectionTimedOut(connection.ConnectionId);
|
SocketEventSource.Log.ConnectionTimedOut(connection.ConnectionId);
|
||||||
|
|
@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DisposeAndRemoveAsync(DefaultConnectionContext connection)
|
public async Task DisposeAndRemoveAsync(HttpConnectionContext connection)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -19,10 +19,10 @@ namespace Microsoft.AspNetCore.Sockets.Internal.Transports
|
||||||
private readonly WebSocketOptions _options;
|
private readonly WebSocketOptions _options;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IDuplexPipe _application;
|
private readonly IDuplexPipe _application;
|
||||||
private readonly DefaultConnectionContext _connection;
|
private readonly HttpConnectionContext _connection;
|
||||||
private volatile bool _aborted;
|
private volatile bool _aborted;
|
||||||
|
|
||||||
public WebSocketsTransport(WebSocketOptions options, IDuplexPipe application, DefaultConnectionContext connection, ILoggerFactory loggerFactory)
|
public WebSocketsTransport(WebSocketOptions options, IDuplexPipe application, HttpConnectionContext connection, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
if (options == null)
|
if (options == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ using System.IO.Pipelines;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Connections.Features;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal;
|
using Microsoft.AspNetCore.SignalR.Internal;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal.Formatters;
|
using Microsoft.AspNetCore.SignalR.Internal.Formatters;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
||||||
|
|
@ -16,8 +18,11 @@ using Microsoft.AspNetCore.Sockets;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.SignalR.Tests
|
namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
{
|
{
|
||||||
public class TestClient : IDisposable
|
public class TestClient : ITransferFormatFeature, IConnectionHeartbeatFeature, IDisposable
|
||||||
{
|
{
|
||||||
|
private object _heartbeatLock = new object();
|
||||||
|
private List<(Action<object> handler, object state)> _heartbeatHandlers;
|
||||||
|
|
||||||
private static int _id;
|
private static int _id;
|
||||||
private readonly IHubProtocol _protocol;
|
private readonly IHubProtocol _protocol;
|
||||||
private readonly IInvocationBinder _invocationBinder;
|
private readonly IInvocationBinder _invocationBinder;
|
||||||
|
|
@ -28,12 +33,20 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
public Task Connected => ((TaskCompletionSource<bool>)Connection.Items["ConnectedTask"]).Task;
|
public Task Connected => ((TaskCompletionSource<bool>)Connection.Items["ConnectedTask"]).Task;
|
||||||
public HandshakeResponseMessage HandshakeResponseMessage { get; private set; }
|
public HandshakeResponseMessage HandshakeResponseMessage { get; private set; }
|
||||||
|
|
||||||
|
public TransferFormat SupportedFormats { get; set; } = TransferFormat.Text | TransferFormat.Binary;
|
||||||
|
|
||||||
|
public TransferFormat ActiveFormat { get; set; }
|
||||||
|
|
||||||
public TestClient(bool synchronousCallbacks = false, IHubProtocol protocol = null, IInvocationBinder invocationBinder = null, bool addClaimId = false)
|
public TestClient(bool synchronousCallbacks = false, IHubProtocol protocol = null, IInvocationBinder invocationBinder = null, bool addClaimId = false)
|
||||||
{
|
{
|
||||||
var options = new PipeOptions(readerScheduler: synchronousCallbacks ? PipeScheduler.Inline : null);
|
var options = new PipeOptions(readerScheduler: synchronousCallbacks ? PipeScheduler.Inline : null);
|
||||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||||
Connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);
|
Connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);
|
||||||
|
|
||||||
|
// Add features SignalR needs for testing
|
||||||
|
Connection.Features.Set<ITransferFormatFeature>(this);
|
||||||
|
Connection.Features.Set<IConnectionHeartbeatFeature>(this);
|
||||||
|
|
||||||
var claimValue = Interlocked.Increment(ref _id).ToString();
|
var claimValue = Interlocked.Increment(ref _id).ToString();
|
||||||
var claims = new List<Claim> { new Claim(ClaimTypes.Name, claimValue) };
|
var claims = new List<Claim> { new Claim(ClaimTypes.Name, claimValue) };
|
||||||
if (addClaimId)
|
if (addClaimId)
|
||||||
|
|
@ -269,6 +282,33 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
return Guid.NewGuid().ToString("N");
|
return Guid.NewGuid().ToString("N");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnHeartbeat(Action<object> action, object state)
|
||||||
|
{
|
||||||
|
lock (_heartbeatLock)
|
||||||
|
{
|
||||||
|
if (_heartbeatHandlers == null)
|
||||||
|
{
|
||||||
|
_heartbeatHandlers = new List<(Action<object> handler, object state)>();
|
||||||
|
}
|
||||||
|
_heartbeatHandlers.Add((action, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TickHeartbeat()
|
||||||
|
{
|
||||||
|
lock (_heartbeatLock)
|
||||||
|
{
|
||||||
|
if (_heartbeatHandlers == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (handler, state) in _heartbeatHandlers)
|
||||||
|
{
|
||||||
|
handler(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private class DefaultInvocationBinder : IInvocationBinder
|
private class DefaultInvocationBinder : IInvocationBinder
|
||||||
{
|
{
|
||||||
public IReadOnlyList<Type> GetParameterTypes(string methodName)
|
public IReadOnlyList<Type> GetParameterTypes(string methodName)
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
|
|
||||||
using (var client = new TestClient(protocol: new MessagePackHubProtocol()))
|
using (var client = new TestClient(protocol: new MessagePackHubProtocol()))
|
||||||
{
|
{
|
||||||
client.Connection.SupportedFormats = TransferFormat.Text;
|
client.SupportedFormats = TransferFormat.Text;
|
||||||
|
|
||||||
var connectionHandlerTask = await client.ConnectAsync(connectionHandler);
|
var connectionHandlerTask = await client.ConnectAsync(connectionHandler);
|
||||||
|
|
||||||
|
|
@ -1430,7 +1430,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
|
|
||||||
using (var client = new TestClient(synchronousCallbacks: false, protocol: protocol, invocationBinder: invocationBinder.Object))
|
using (var client = new TestClient(synchronousCallbacks: false, protocol: protocol, invocationBinder: invocationBinder.Object))
|
||||||
{
|
{
|
||||||
client.Connection.SupportedFormats = protocol.TransferFormat;
|
client.SupportedFormats = protocol.TransferFormat;
|
||||||
|
|
||||||
var connectionHandlerTask = await client.ConnectAsync(connectionHandler);
|
var connectionHandlerTask = await client.ConnectAsync(connectionHandler);
|
||||||
|
|
||||||
|
|
@ -1711,7 +1711,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
var msgPackOptions = serviceProvider.GetRequiredService<IOptions<MessagePackHubProtocolOptions>>();
|
var msgPackOptions = serviceProvider.GetRequiredService<IOptions<MessagePackHubProtocolOptions>>();
|
||||||
using (var client = new TestClient(synchronousCallbacks: false, protocol: new MessagePackHubProtocol(msgPackOptions)))
|
using (var client = new TestClient(synchronousCallbacks: false, protocol: new MessagePackHubProtocol(msgPackOptions)))
|
||||||
{
|
{
|
||||||
client.Connection.SupportedFormats = TransferFormat.Binary;
|
client.SupportedFormats = TransferFormat.Binary;
|
||||||
var connectionHandlerTask = await client.ConnectAsync(connectionHandler);
|
var connectionHandlerTask = await client.ConnectAsync(connectionHandler);
|
||||||
|
|
||||||
await client.Connected.OrTimeout();
|
await client.Connected.OrTimeout();
|
||||||
|
|
@ -1860,7 +1860,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
// being available for the endpoint to run.
|
// being available for the endpoint to run.
|
||||||
for (var i = 0; i < 50; i += 1)
|
for (var i = 0; i < 50; i += 1)
|
||||||
{
|
{
|
||||||
client.Connection.TickHeartbeat();
|
client.TickHeartbeat();
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -738,7 +738,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
await request1;
|
await request1;
|
||||||
|
|
||||||
Assert.Equal(StatusCodes.Status204NoContent, context1.Response.StatusCode);
|
Assert.Equal(StatusCodes.Status204NoContent, context1.Response.StatusCode);
|
||||||
Assert.Equal(DefaultConnectionContext.ConnectionStatus.Active, connection.Status);
|
Assert.Equal(HttpConnectionContext.ConnectionStatus.Active, connection.Status);
|
||||||
|
|
||||||
Assert.False(request2.IsCompleted);
|
Assert.False(request2.IsCompleted);
|
||||||
|
|
||||||
|
|
@ -757,7 +757,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
{
|
{
|
||||||
var manager = CreateConnectionManager(loggerFactory);
|
var manager = CreateConnectionManager(loggerFactory);
|
||||||
var connection = manager.CreateConnection();
|
var connection = manager.CreateConnection();
|
||||||
connection.Status = DefaultConnectionContext.ConnectionStatus.Disposed;
|
connection.Status = HttpConnectionContext.ConnectionStatus.Disposed;
|
||||||
|
|
||||||
var dispatcher = new HttpConnectionDispatcher(manager, loggerFactory);
|
var dispatcher = new HttpConnectionDispatcher(manager, loggerFactory);
|
||||||
|
|
||||||
|
|
@ -804,7 +804,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
|
|
||||||
await task;
|
await task;
|
||||||
|
|
||||||
Assert.Equal(DefaultConnectionContext.ConnectionStatus.Inactive, connection.Status);
|
Assert.Equal(HttpConnectionContext.ConnectionStatus.Inactive, connection.Status);
|
||||||
Assert.NotNull(connection.GetHttpContext());
|
Assert.NotNull(connection.GetHttpContext());
|
||||||
|
|
||||||
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
|
||||||
|
|
@ -1459,9 +1459,9 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConnectionManager CreateConnectionManager(ILoggerFactory loggerFactory)
|
private static HttpConnectionManager CreateConnectionManager(ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
return new ConnectionManager(new Logger<ConnectionManager>(loggerFactory ?? new LoggerFactory()), new EmptyApplicationLifetime());
|
return new HttpConnectionManager(new Logger<HttpConnectionManager>(loggerFactory ?? new LoggerFactory()), new EmptyApplicationLifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetContentAsString(Stream body)
|
private string GetContentAsString(Stream body)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets.Tests
|
namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
{
|
{
|
||||||
public class ConnectionManagerTests
|
public class HttpConnectionManagerTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void NewConnectionsHaveConnectionId()
|
public void NewConnectionsHaveConnectionId()
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
var connection = connectionManager.CreateConnection();
|
var connection = connectionManager.CreateConnection();
|
||||||
|
|
||||||
Assert.NotNull(connection.ConnectionId);
|
Assert.NotNull(connection.ConnectionId);
|
||||||
Assert.Equal(DefaultConnectionContext.ConnectionStatus.Inactive, connection.Status);
|
Assert.Equal(HttpConnectionContext.ConnectionStatus.Inactive, connection.Status);
|
||||||
Assert.Null(connection.ApplicationTask);
|
Assert.Null(connection.ApplicationTask);
|
||||||
Assert.Null(connection.TransportTask);
|
Assert.Null(connection.TransportTask);
|
||||||
Assert.Null(connection.Cancellation);
|
Assert.Null(connection.Cancellation);
|
||||||
|
|
@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
Assert.NotNull(connection.Transport);
|
Assert.NotNull(connection.Transport);
|
||||||
|
|
||||||
await connection.DisposeAsync();
|
await connection.DisposeAsync();
|
||||||
Assert.Equal(DefaultConnectionContext.ConnectionStatus.Disposed, connection.Status);
|
Assert.Equal(HttpConnectionContext.ConnectionStatus.Disposed, connection.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -224,10 +224,10 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
await tcs.Task.OrTimeout();
|
await tcs.Task.OrTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConnectionManager CreateConnectionManager(IApplicationLifetime lifetime = null)
|
private static HttpConnectionManager CreateConnectionManager(IApplicationLifetime lifetime = null)
|
||||||
{
|
{
|
||||||
lifetime = lifetime ?? new EmptyApplicationLifetime();
|
lifetime = lifetime ?? new EmptyApplicationLifetime();
|
||||||
return new ConnectionManager(new Logger<ConnectionManager>(new LoggerFactory()), lifetime);
|
return new HttpConnectionManager(new Logger<HttpConnectionManager>(new LoggerFactory()), lifetime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ using System.IO.Pipelines;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal.Transports;
|
using Microsoft.AspNetCore.Sockets.Internal.Transports;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal.Transports;
|
using Microsoft.AspNetCore.Sockets.Internal.Transports;
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
// Give the server socket to the transport and run it
|
// Give the server socket to the transport and run it
|
||||||
|
|
@ -79,11 +79,11 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
connectionContext.ActiveFormat = transferFormat;
|
connectionContext.ActiveFormat = transferFormat;
|
||||||
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
|
|
@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
// Give the server socket to the transport and run it
|
// Give the server socket to the transport and run it
|
||||||
|
|
@ -169,11 +169,11 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(new WebSocketOptions(), connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
// Give the server socket to the transport and run it
|
// Give the server socket to the transport and run it
|
||||||
|
|
@ -201,7 +201,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
|
|
@ -210,7 +210,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
CloseTimeout = TimeSpan.FromSeconds(1)
|
CloseTimeout = TimeSpan.FromSeconds(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
var serverSocket = await feature.AcceptAsync();
|
var serverSocket = await feature.AcceptAsync();
|
||||||
|
|
@ -236,7 +236,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
|
|
@ -245,7 +245,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
CloseTimeout = TimeSpan.FromSeconds(1)
|
CloseTimeout = TimeSpan.FromSeconds(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
var serverSocket = await feature.AcceptAsync();
|
var serverSocket = await feature.AcceptAsync();
|
||||||
|
|
@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
|
|
@ -281,7 +281,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
CloseTimeout = TimeSpan.FromSeconds(20)
|
CloseTimeout = TimeSpan.FromSeconds(20)
|
||||||
};
|
};
|
||||||
|
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
var serverSocket = await feature.AcceptAsync();
|
var serverSocket = await feature.AcceptAsync();
|
||||||
|
|
@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
using (StartLog(out var loggerFactory, LogLevel.Debug))
|
||||||
{
|
{
|
||||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||||
var connection = new DefaultConnectionContext("foo", pair.Transport, pair.Application);
|
var connection = new HttpConnectionContext("foo", pair.Transport, pair.Application);
|
||||||
|
|
||||||
using (var feature = new TestWebSocketConnectionFeature())
|
using (var feature = new TestWebSocketConnectionFeature())
|
||||||
{
|
{
|
||||||
|
|
@ -321,7 +321,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
CloseTimeout = TimeSpan.FromSeconds(20)
|
CloseTimeout = TimeSpan.FromSeconds(20)
|
||||||
};
|
};
|
||||||
|
|
||||||
var connectionContext = new DefaultConnectionContext(string.Empty, null, null);
|
var connectionContext = new HttpConnectionContext(string.Empty, null, null);
|
||||||
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
var ws = new WebSocketsTransport(options, connection.Application, connectionContext, loggerFactory);
|
||||||
|
|
||||||
var serverSocket = await feature.AcceptAsync();
|
var serverSocket = await feature.AcceptAsync();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue