Pass options to HubConnectionContext (#11382)
This commit is contained in:
parent
c987ce5b3c
commit
e8181ae479
|
|
@ -20,7 +20,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
{
|
||||
public static HubConnectionContext Create(ConnectionContext connection, IHubProtocol protocol = null, string userIdentifier = null)
|
||||
{
|
||||
return new HubConnectionContext(connection, TimeSpan.FromSeconds(15), NullLoggerFactory.Instance)
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = TimeSpan.FromSeconds(15),
|
||||
};
|
||||
|
||||
return new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance)
|
||||
{
|
||||
Protocol = protocol ?? new JsonHubProtocol(),
|
||||
UserIdentifier = userIdentifier,
|
||||
|
|
@ -29,15 +34,20 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
|
||||
public static MockHubConnectionContext CreateMock(ConnectionContext connection)
|
||||
{
|
||||
return new MockHubConnectionContext(connection, TimeSpan.FromSeconds(15), NullLoggerFactory.Instance, TimeSpan.FromSeconds(15), streamBufferCapacity: 10);
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = TimeSpan.FromSeconds(15),
|
||||
ClientTimeoutInterval = TimeSpan.FromSeconds(15),
|
||||
StreamBufferCapacity = 10,
|
||||
};
|
||||
return new MockHubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
public class MockHubConnectionContext : HubConnectionContext
|
||||
{
|
||||
public MockHubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval, int streamBufferCapacity)
|
||||
: base(connectionContext, keepAliveInterval, loggerFactory, clientTimeoutInterval, streamBufferCapacity)
|
||||
public MockHubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
|
||||
: base(connectionContext, contextOptions, loggerFactory)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override ValueTask WriteAsync(HubMessage message, CancellationToken cancellationToken = default)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,11 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
|||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(options, options);
|
||||
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
|
||||
var hubConnection = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = Timeout.InfiniteTimeSpan,
|
||||
};
|
||||
var hubConnection = new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
|
||||
hubConnection.Protocol = protocol;
|
||||
_hubLifetimeManager.OnConnectedAsync(hubConnection).GetAwaiter().GetResult();
|
||||
_hubLifetimeManager.AddToGroupAsync(connection.ConnectionId, TestGroupName).GetAwaiter().GetResult();
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -46,7 +44,11 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
|||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
|
||||
|
||||
_connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = TimeSpan.Zero,
|
||||
};
|
||||
_connectionContext = new NoErrorHubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
|
||||
|
||||
_connectionContext.Protocol = new FakeHubProtocol();
|
||||
}
|
||||
|
|
@ -83,7 +85,8 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
|||
{
|
||||
public TaskCompletionSource<object> ReceivedCompleted = new TaskCompletionSource<object>();
|
||||
|
||||
public NoErrorHubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory) : base(connectionContext, keepAliveInterval, loggerFactory)
|
||||
public NoErrorHubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
|
||||
: base(connectionContext, contextOptions, loggerFactory)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,11 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
|||
ConnectionId = connectionId,
|
||||
Transport = new TestDuplexPipe(ForceAsync)
|
||||
};
|
||||
var hubConnectionContext = new HubConnectionContext(connectionContext, TimeSpan.Zero, NullLoggerFactory.Instance);
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = TimeSpan.Zero,
|
||||
};
|
||||
var hubConnectionContext = new HubConnectionContext(connectionContext, contextOptions, NullLoggerFactory.Instance);
|
||||
hubConnectionContext.UserIdentifier = userIdentifier;
|
||||
hubConnectionContext.Protocol = jsonHubProtocol;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.SignalR.Internal;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
|
||||
|
|
@ -44,7 +43,11 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
|||
_pipe = new TestDuplexPipe();
|
||||
|
||||
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), _pipe, _pipe);
|
||||
_hubConnectionContext = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = Timeout.InfiniteTimeSpan,
|
||||
};
|
||||
_hubConnectionContext = new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
|
||||
|
||||
_successHubProtocolResolver = new TestHubProtocolResolver(new NewtonsoftJsonHubProtocol());
|
||||
_failureHubProtocolResolver = new TestHubProtocolResolver(null);
|
||||
|
|
|
|||
|
|
@ -127,9 +127,7 @@ namespace Microsoft.AspNetCore.SignalR
|
|||
}
|
||||
public partial class HubConnectionContext
|
||||
{
|
||||
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, System.TimeSpan keepAliveInterval, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
|
||||
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, System.TimeSpan keepAliveInterval, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.TimeSpan clientTimeoutInterval) { }
|
||||
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, System.TimeSpan keepAliveInterval, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.TimeSpan clientTimeoutInterval, int streamBufferCapacity) { }
|
||||
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, Microsoft.AspNetCore.SignalR.HubConnectionContextOptions contextOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
|
||||
public virtual System.Threading.CancellationToken ConnectionAborted { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public virtual string ConnectionId { get { throw null; } }
|
||||
public virtual Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get { throw null; } }
|
||||
|
|
@ -141,6 +139,13 @@ namespace Microsoft.AspNetCore.SignalR
|
|||
public virtual System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.SignalR.Protocol.HubMessage message, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
|
||||
public virtual System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.SignalR.SerializedHubMessage message, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
|
||||
}
|
||||
public partial class HubConnectionContextOptions
|
||||
{
|
||||
public HubConnectionContextOptions() { }
|
||||
public System.TimeSpan ClientTimeoutInterval { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public System.TimeSpan KeepAliveInterval { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public int StreamBufferCapacity { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
public partial class HubConnectionHandler<THub> : Microsoft.AspNetCore.Connections.ConnectionHandler where THub : Microsoft.AspNetCore.SignalR.Hub
|
||||
{
|
||||
public HubConnectionHandler(Microsoft.AspNetCore.SignalR.HubLifetimeManager<THub> lifetimeManager, Microsoft.AspNetCore.SignalR.IHubProtocolResolver protocolResolver, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.HubOptions> globalHubOptions, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.HubOptions<THub>> hubOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.SignalR.IUserIdProvider userIdProvider, Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) { }
|
||||
|
|
|
|||
|
|
@ -48,37 +48,17 @@ namespace Microsoft.AspNetCore.SignalR
|
|||
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
|
||||
/// <param name="keepAliveInterval">The keep alive interval. If no messages are sent by the server in this interval, a Ping message will be sent.</param>
|
||||
/// <param name="loggerFactory">The logger factory.</param>
|
||||
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory)
|
||||
: this(connectionContext, keepAliveInterval, loggerFactory, HubOptionsSetup.DefaultClientTimeoutInterval, HubOptionsSetup.DefaultStreamBufferCapacity) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
|
||||
/// <param name="keepAliveInterval">The keep alive interval. If no messages are sent by the server in this interval, a Ping message will be sent.</param>
|
||||
/// <param name="loggerFactory">The logger factory.</param>
|
||||
/// <param name="clientTimeoutInterval">Clients we haven't heard from in this interval are assumed to have disconnected.</param>
|
||||
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval)
|
||||
: this(connectionContext, keepAliveInterval, loggerFactory, clientTimeoutInterval, HubOptionsSetup.DefaultStreamBufferCapacity) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
|
||||
/// <param name="keepAliveInterval">The keep alive interval. If no messages are sent by the server in this interval, a Ping message will be sent.</param>
|
||||
/// <param name="loggerFactory">The logger factory.</param>
|
||||
/// <param name="clientTimeoutInterval">Clients we haven't heard from in this interval are assumed to have disconnected.</param>
|
||||
/// <param name="streamBufferCapacity">The buffer size for client upload streams</param>
|
||||
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval, int streamBufferCapacity)
|
||||
/// <param name="contextOptions">The options to configure the HubConnectionContext.</param>
|
||||
public HubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
|
||||
{
|
||||
_keepAliveInterval = contextOptions.KeepAliveInterval.Ticks;
|
||||
_clientTimeoutInterval = contextOptions.ClientTimeoutInterval.Ticks;
|
||||
_streamBufferCapacity = contextOptions.StreamBufferCapacity;
|
||||
|
||||
_connectionContext = connectionContext;
|
||||
_logger = loggerFactory.CreateLogger<HubConnectionContext>();
|
||||
ConnectionAborted = _connectionAbortedTokenSource.Token;
|
||||
_keepAliveInterval = keepAliveInterval.Ticks;
|
||||
_clientTimeoutInterval = clientTimeoutInterval.Ticks;
|
||||
_streamBufferCapacity = streamBufferCapacity;
|
||||
}
|
||||
|
||||
internal StreamTracker StreamTracker
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR
|
||||
{
|
||||
/// <summary>
|
||||
/// Options used to configure <see cref="HubConnectionContext"/>.
|
||||
/// </summary>
|
||||
public class HubConnectionContextOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the interval used to send keep alive pings to connected clients.
|
||||
/// </summary>
|
||||
public TimeSpan KeepAliveInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time window clients have to send a message before the server closes the connection.
|
||||
/// </summary>
|
||||
public TimeSpan ClientTimeoutInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the max buffer size for client upload streams.
|
||||
/// </summary>
|
||||
public int StreamBufferCapacity { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ using Microsoft.AspNetCore.SignalR.Internal;
|
|||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR
|
||||
|
|
@ -75,21 +74,26 @@ namespace Microsoft.AspNetCore.SignalR
|
|||
public override async Task OnConnectedAsync(ConnectionContext connection)
|
||||
{
|
||||
// We check to see if HubOptions<THub> are set because those take precedence over global hub options.
|
||||
// Then set the keepAlive and handshakeTimeout values to the defaults in HubOptionsSetup incase they were explicitly set to null.
|
||||
var keepAlive = _hubOptions.KeepAliveInterval ?? _globalHubOptions.KeepAliveInterval ?? HubOptionsSetup.DefaultKeepAliveInterval;
|
||||
var clientTimeout = _hubOptions.ClientTimeoutInterval ?? _globalHubOptions.ClientTimeoutInterval ?? HubOptionsSetup.DefaultClientTimeoutInterval;
|
||||
var handshakeTimeout = _hubOptions.HandshakeTimeout ?? _globalHubOptions.HandshakeTimeout ?? HubOptionsSetup.DefaultHandshakeTimeout;
|
||||
var streamBufferCapacity = _hubOptions.StreamBufferCapacity ?? _globalHubOptions.StreamBufferCapacity ?? HubOptionsSetup.DefaultStreamBufferCapacity;
|
||||
var supportedProtocols = _hubOptions.SupportedProtocols ?? _globalHubOptions.SupportedProtocols;
|
||||
// Then set the keepAlive and handshakeTimeout values to the defaults in HubOptionsSetup when they were explicitly set to null.
|
||||
|
||||
if (supportedProtocols != null && supportedProtocols.Count == 0)
|
||||
var supportedProtocols = _hubOptions.SupportedProtocols ?? _globalHubOptions.SupportedProtocols;
|
||||
if (supportedProtocols == null || supportedProtocols.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("There are no supported protocols");
|
||||
}
|
||||
|
||||
var handshakeTimeout = _hubOptions.HandshakeTimeout ?? _globalHubOptions.HandshakeTimeout ?? HubOptionsSetup.DefaultHandshakeTimeout;
|
||||
|
||||
var contextOptions = new HubConnectionContextOptions()
|
||||
{
|
||||
KeepAliveInterval = _hubOptions.KeepAliveInterval ?? _globalHubOptions.KeepAliveInterval ?? HubOptionsSetup.DefaultKeepAliveInterval,
|
||||
ClientTimeoutInterval = _hubOptions.ClientTimeoutInterval ?? _globalHubOptions.ClientTimeoutInterval ?? HubOptionsSetup.DefaultClientTimeoutInterval,
|
||||
StreamBufferCapacity = _hubOptions.StreamBufferCapacity ?? _globalHubOptions.StreamBufferCapacity ?? HubOptionsSetup.DefaultStreamBufferCapacity,
|
||||
};
|
||||
|
||||
Log.ConnectedStarting(_logger);
|
||||
|
||||
var connectionContext = new HubConnectionContext(connection, keepAlive, _loggerFactory, clientTimeout, streamBufferCapacity);
|
||||
var connectionContext = new HubConnectionContext(connection, contextOptions, _loggerFactory);
|
||||
|
||||
var resolvedSupportedProtocols = (supportedProtocols as IReadOnlyList<string>) ?? supportedProtocols.ToList();
|
||||
if (!await connectionContext.HandshakeAsync(handshakeTimeout, resolvedSupportedProtocols, _protocolResolver, _userIdProvider, _enableDetailedErrors))
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.SignalR
|
|||
// for all available protocols.
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the interval used by the server to timeout incoming handshake requests by clients. The default timeout is 15 seconds
|
||||
/// Gets or sets the interval used by the server to timeout incoming handshake requests by clients. The default timeout is 15 seconds.
|
||||
/// </summary>
|
||||
public TimeSpan? HandshakeTimeout { get; set; } = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -2309,6 +2309,54 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HubOptionsCanNotHaveNullSupportedProtocols()
|
||||
{
|
||||
using (StartVerifiableLog())
|
||||
{
|
||||
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
|
||||
{
|
||||
services.AddSignalR(o =>
|
||||
{
|
||||
o.SupportedProtocols = null;
|
||||
});
|
||||
}, LoggerFactory);
|
||||
|
||||
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<MethodHub>>();
|
||||
|
||||
var msgPackOptions = serviceProvider.GetRequiredService<IOptions<MessagePackHubProtocolOptions>>();
|
||||
using (var client = new TestClient(protocol: new MessagePackHubProtocol(msgPackOptions)))
|
||||
{
|
||||
client.SupportedFormats = TransferFormat.Binary;
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await await client.ConnectAsync(connectionHandler, expectedHandshakeResponseMessage: false)).OrTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HubOptionsCanNotHaveEmptySupportedProtocols()
|
||||
{
|
||||
using (StartVerifiableLog())
|
||||
{
|
||||
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
|
||||
{
|
||||
services.AddSignalR(o =>
|
||||
{
|
||||
o.SupportedProtocols = new List<string>();
|
||||
});
|
||||
}, LoggerFactory);
|
||||
|
||||
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<MethodHub>>();
|
||||
|
||||
var msgPackOptions = serviceProvider.GetRequiredService<IOptions<MessagePackHubProtocolOptions>>();
|
||||
using (var client = new TestClient(protocol: new MessagePackHubProtocol(msgPackOptions)))
|
||||
{
|
||||
client.SupportedFormats = TransferFormat.Binary;
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await await client.ConnectAsync(connectionHandler, expectedHandshakeResponseMessage: false)).OrTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConnectionUserIdIsAssignedByUserIdProvider()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue