Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit 345190e

Browse files
Add timeout to Negotiate (#736)
1 parent a4053ac commit 345190e

File tree

2 files changed

+44
-17
lines changed

2 files changed

+44
-17
lines changed

src/Microsoft.AspNetCore.SignalR/HubEndPoint.cs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class HubEndPoint<THub> : IInvocationBinder where THub : Hub
2727
{
2828
private static readonly Base64Encoder Base64Encoder = new Base64Encoder();
2929
private static readonly PassThroughEncoder PassThroughEncoder = new PassThroughEncoder();
30+
private static readonly TimeSpan NegotiateTimeout = TimeSpan.FromSeconds(5);
3031

3132
private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);
3233

@@ -108,35 +109,46 @@ async Task WriteToTransport()
108109

109110
private async Task<bool> ProcessNegotiate(HubConnectionContext connection)
110111
{
111-
while (await connection.Input.WaitToReadAsync())
112+
try
112113
{
113-
while (connection.Input.TryRead(out var buffer))
114+
using (var cts = new CancellationTokenSource())
114115
{
115-
if (NegotiationProtocol.TryParseMessage(buffer, out var negotiationMessage))
116+
cts.CancelAfter(NegotiateTimeout);
117+
while (await connection.Input.WaitToReadAsync(cts.Token))
116118
{
117-
var protocol = _protocolResolver.GetProtocol(negotiationMessage.Protocol, connection);
119+
while (connection.Input.TryRead(out var buffer))
120+
{
121+
if (NegotiationProtocol.TryParseMessage(buffer, out var negotiationMessage))
122+
{
123+
var protocol = _protocolResolver.GetProtocol(negotiationMessage.Protocol, connection);
118124

119-
var transportCapabilities = connection.Features.Get<IConnectionTransportFeature>()?.TransportCapabilities
120-
?? throw new InvalidOperationException("Unable to read transport capabilities.");
125+
var transportCapabilities = connection.Features.Get<IConnectionTransportFeature>()?.TransportCapabilities
126+
?? throw new InvalidOperationException("Unable to read transport capabilities.");
121127

122-
var dataEncoder = (protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) == 0)
123-
? (IDataEncoder)Base64Encoder
124-
: PassThroughEncoder;
128+
var dataEncoder = (protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) == 0)
129+
? (IDataEncoder)Base64Encoder
130+
: PassThroughEncoder;
125131

126-
var transferModeFeature = connection.Features.Get<ITransferModeFeature>() ??
127-
throw new InvalidOperationException("Unable to read transfer mode.");
132+
var transferModeFeature = connection.Features.Get<ITransferModeFeature>() ??
133+
throw new InvalidOperationException("Unable to read transfer mode.");
128134

129-
transferModeFeature.TransferMode =
130-
(protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) != 0)
131-
? TransferMode.Binary
132-
: TransferMode.Text;
135+
transferModeFeature.TransferMode =
136+
(protocol.Type == ProtocolType.Binary && (transportCapabilities & TransferMode.Binary) != 0)
137+
? TransferMode.Binary
138+
: TransferMode.Text;
133139

134-
connection.ProtocolReaderWriter = new HubProtocolReaderWriter(protocol, dataEncoder);
140+
connection.ProtocolReaderWriter = new HubProtocolReaderWriter(protocol, dataEncoder);
135141

136-
return true;
142+
return true;
143+
}
144+
}
137145
}
138146
}
139147
}
148+
catch (OperationCanceledException)
149+
{
150+
_logger.LogDebug("Negotiate was canceled.");
151+
}
140152

141153
return false;
142154
}

test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ public async Task MissingNegotiateAndMessageSentFromHubConnectionCanBeDisposedCl
5959
}
6060
}
6161

62+
[Fact]
63+
public async Task NegotiateTimesOut()
64+
{
65+
var serviceProvider = CreateServiceProvider();
66+
var endPoint = serviceProvider.GetService<HubEndPoint<SimpleHub>>();
67+
68+
using (var client = new TestClient())
69+
{
70+
// TestClient automatically writes negotiate, for this test we want to assume negotiate never gets sent
71+
client.Connection.Transport.In.TryRead(out var item);
72+
73+
await endPoint.OnConnectedAsync(client.Connection).OrTimeout(TimeSpan.FromSeconds(10));
74+
}
75+
}
76+
6277
[Fact]
6378
public async Task LifetimeManagerOnDisconnectedAsyncCalledIfLifetimeManagerOnConnectedAsyncThrows()
6479
{

0 commit comments

Comments
 (0)