Add timeout to Negotiate (#736)
This commit is contained in:
parent
a4053acd06
commit
345190e6a9
|
|
@ -27,6 +27,7 @@ namespace Microsoft.AspNetCore.SignalR
|
||||||
{
|
{
|
||||||
private static readonly Base64Encoder Base64Encoder = new Base64Encoder();
|
private static readonly Base64Encoder Base64Encoder = new Base64Encoder();
|
||||||
private static readonly PassThroughEncoder PassThroughEncoder = new PassThroughEncoder();
|
private static readonly PassThroughEncoder PassThroughEncoder = new PassThroughEncoder();
|
||||||
|
private static readonly TimeSpan NegotiateTimeout = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);
|
private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
@ -108,35 +109,46 @@ namespace Microsoft.AspNetCore.SignalR
|
||||||
|
|
||||||
private async Task<bool> ProcessNegotiate(HubConnectionContext connection)
|
private async Task<bool> ProcessNegotiate(HubConnectionContext connection)
|
||||||
{
|
{
|
||||||
while (await connection.Input.WaitToReadAsync())
|
try
|
||||||
{
|
{
|
||||||
while (connection.Input.TryRead(out var buffer))
|
using (var cts = new CancellationTokenSource())
|
||||||
{
|
{
|
||||||
if (NegotiationProtocol.TryParseMessage(buffer, out var negotiationMessage))
|
cts.CancelAfter(NegotiateTimeout);
|
||||||
|
while (await connection.Input.WaitToReadAsync(cts.Token))
|
||||||
{
|
{
|
||||||
var protocol = _protocolResolver.GetProtocol(negotiationMessage.Protocol, connection);
|
while (connection.Input.TryRead(out var buffer))
|
||||||
|
{
|
||||||
|
if (NegotiationProtocol.TryParseMessage(buffer, out var negotiationMessage))
|
||||||
|
{
|
||||||
|
var protocol = _protocolResolver.GetProtocol(negotiationMessage.Protocol, connection);
|
||||||
|
|
||||||
var transportCapabilities = connection.Features.Get<IConnectionTransportFeature>()?.TransportCapabilities
|
var transportCapabilities = connection.Features.Get<IConnectionTransportFeature>()?.TransportCapabilities
|
||||||
?? throw new InvalidOperationException("Unable to read transport capabilities.");
|
?? throw new InvalidOperationException("Unable to read transport capabilities.");
|
||||||
|
|
||||||
var dataEncoder = (protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) == 0)
|
var dataEncoder = (protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) == 0)
|
||||||
? (IDataEncoder)Base64Encoder
|
? (IDataEncoder)Base64Encoder
|
||||||
: PassThroughEncoder;
|
: PassThroughEncoder;
|
||||||
|
|
||||||
var transferModeFeature = connection.Features.Get<ITransferModeFeature>() ??
|
var transferModeFeature = connection.Features.Get<ITransferModeFeature>() ??
|
||||||
throw new InvalidOperationException("Unable to read transfer mode.");
|
throw new InvalidOperationException("Unable to read transfer mode.");
|
||||||
|
|
||||||
transferModeFeature.TransferMode =
|
transferModeFeature.TransferMode =
|
||||||
(protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) != 0)
|
(protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) != 0)
|
||||||
? TransferMode.Binary
|
? TransferMode.Binary
|
||||||
: TransferMode.Text;
|
: TransferMode.Text;
|
||||||
|
|
||||||
connection.ProtocolReaderWriter = new HubProtocolReaderWriter(protocol, dataEncoder);
|
connection.ProtocolReaderWriter = new HubProtocolReaderWriter(protocol, dataEncoder);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("Negotiate was canceled.");
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,21 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task NegotiateTimesOut()
|
||||||
|
{
|
||||||
|
var serviceProvider = CreateServiceProvider();
|
||||||
|
var endPoint = serviceProvider.GetService<HubEndPoint<SimpleHub>>();
|
||||||
|
|
||||||
|
using (var client = new TestClient())
|
||||||
|
{
|
||||||
|
// TestClient automatically writes negotiate, for this test we want to assume negotiate never gets sent
|
||||||
|
client.Connection.Transport.In.TryRead(out var item);
|
||||||
|
|
||||||
|
await endPoint.OnConnectedAsync(client.Connection).OrTimeout(TimeSpan.FromSeconds(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task LifetimeManagerOnDisconnectedAsyncCalledIfLifetimeManagerOnConnectedAsyncThrows()
|
public async Task LifetimeManagerOnDisconnectedAsyncCalledIfLifetimeManagerOnConnectedAsyncThrows()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue