Skip to content

Commit 6a8ede0

Browse files
authored
Further making Microsoft.AspNetCore.Sockets "not a thing" (#1599)
- This PR attempts to move things where they are needed instead of where they happened to be used. As a result we should now have Sockets.Abstractions and Sockets down to the minimal set of things required to make them run. Sockets.Abstractions should go away in favor of Protocol.Abstractions and Sockets contains the EndPoint abstraction and related types. - Moved ConnectionManager and friends to Sockets.Http. -Removed Sockets and moved everything into Sockets.Abstractions. - Moved DefaultConnection and put it in Sockets.Abstractions.
1 parent bc6ed02 commit 6a8ede0

29 files changed

+135
-133
lines changed

SignalR.sln

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C4BC
2222
EndProject
2323
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocketsSample", "samples\SocketsSample\SocketsSample.csproj", "{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}"
2424
EndProject
25-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Sockets", "src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj", "{1715EA8D-8E13-4ACF-8BCA-57D048E55ED8}"
26-
EndProject
2725
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6A35B453-52EC-48AF-89CA-D4A69800F131}"
2826
ProjectSection(SolutionItems) = preProject
2927
test\Directory.Build.props = test\Directory.Build.props
@@ -101,10 +99,6 @@ Global
10199
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
102100
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
103101
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}.Release|Any CPU.Build.0 = Release|Any CPU
104-
{1715EA8D-8E13-4ACF-8BCA-57D048E55ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
105-
{1715EA8D-8E13-4ACF-8BCA-57D048E55ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
106-
{1715EA8D-8E13-4ACF-8BCA-57D048E55ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
107-
{1715EA8D-8E13-4ACF-8BCA-57D048E55ED8}.Release|Any CPU.Build.0 = Release|Any CPU
108102
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
109103
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
110104
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -227,7 +221,6 @@ Global
227221
EndGlobalSection
228222
GlobalSection(NestedProjects) = preSolution
229223
{C4AEAB04-F341-4539-B6C0-52368FB4BF9E} = {C4BC9889-B49F-41B6-806B-F84941B2549B}
230-
{1715EA8D-8E13-4ACF-8BCA-57D048E55ED8} = {DA69F624-5398-4884-87E4-B816698CDE65}
231224
{AAD719D5-5E31-4ED1-A60F-6EB92EFA66D9} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
232225
{42E76F87-92B6-45AB-BF07-6B811C0F2CAC} = {DA69F624-5398-4884-87E4-B816698CDE65}
233226
{59319B72-38BE-4041-8E5C-FF6938874CE8} = {DA69F624-5398-4884-87E4-B816698CDE65}

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using Microsoft.Extensions.DependencyInjection;
1717
using Microsoft.Extensions.Logging;
1818
using Microsoft.Extensions.Logging.Abstractions;
19-
using DefaultConnectionContext = Microsoft.AspNetCore.Sockets.DefaultConnectionContext;
2019

2120
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
2221
{
@@ -42,7 +41,7 @@ public void GlobalSetup()
4241

4342
var options = new PipeOptions();
4443
var pair = DuplexPipe.CreateConnectionPair(options, options);
45-
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);
44+
var connection = new Sockets.DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);
4645

4746
_connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);
4847

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@
99
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Core\Microsoft.AspNetCore.SignalR.Core.csproj" />
1010
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Common\Microsoft.AspNetCore.SignalR.Common.csproj" />
1111
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Protocols.MsgPack\Microsoft.AspNetCore.SignalR.Protocols.MsgPack.csproj" />
12-
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
1312
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
1413
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
1514
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
15+
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" PrivateAssets="All" />
1616
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
1717
<PackageReference Include="System.Threading.Channels" Version="$(SystemThreadingChannelsPackageVersion)" />
1818
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsPackageVersion)" />
1919
<PackageReference Include="System.Reactive.Linq" Version="$(SystemReactiveLinqPackageVersion)" />
2020
</ItemGroup>
21-
2221
</Project>

client-ts/FunctionalTests/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public void ConfigureServices(IServiceCollection services)
6969
}
7070
};
7171
});
72-
services.AddEndPoint<EchoEndPoint>();
72+
services.AddSingleton<EchoEndPoint>();
7373
}
7474

7575
public void Configure(IApplicationBuilder app, IHostingEnvironment env)

src/Microsoft.AspNetCore.Sockets/ConnectionList.cs renamed to samples/SocialWeather/ConnectionList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace Microsoft.AspNetCore.Sockets
1111
{
12-
public class ConnectionList : IReadOnlyCollection<ConnectionContext>
12+
internal class ConnectionList : IReadOnlyCollection<ConnectionContext>
1313
{
1414
private readonly ConcurrentDictionary<string, ConnectionContext> _connections = new ConcurrentDictionary<string, ConnectionContext>();
1515

samples/SocialWeather/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public void ConfigureServices(IServiceCollection services)
1717
{
1818
services.AddRouting();
1919
services.AddSockets();
20-
services.AddEndPoint<SocialWeatherEndPoint>();
20+
services.AddSingleton<SocialWeatherEndPoint>();
2121
services.AddTransient<PersistentConnectionLifeTimeManager>();
2222
services.AddSingleton(typeof(JsonStreamFormatter<>), typeof(JsonStreamFormatter<>));
2323
services.AddSingleton<PipeWeatherStreamFormatter>();
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections;
6+
using System.Collections.Concurrent;
7+
using System.Collections.Generic;
8+
using Microsoft.AspNetCore.Protocols;
9+
10+
namespace Microsoft.AspNetCore.Sockets
11+
{
12+
internal class ConnectionList : IReadOnlyCollection<ConnectionContext>
13+
{
14+
private readonly ConcurrentDictionary<string, ConnectionContext> _connections = new ConcurrentDictionary<string, ConnectionContext>();
15+
16+
public ConnectionContext this[string connectionId]
17+
{
18+
get
19+
{
20+
if (_connections.TryGetValue(connectionId, out var connection))
21+
{
22+
return connection;
23+
}
24+
return null;
25+
}
26+
}
27+
28+
public int Count => _connections.Count;
29+
30+
public void Add(ConnectionContext connection)
31+
{
32+
_connections.TryAdd(connection.ConnectionId, connection);
33+
}
34+
35+
public void Remove(ConnectionContext connection)
36+
{
37+
_connections.TryRemove(connection.ConnectionId, out var dummy);
38+
}
39+
40+
public IEnumerator<ConnectionContext> GetEnumerator()
41+
{
42+
foreach (var item in _connections)
43+
{
44+
yield return item.Value;
45+
}
46+
}
47+
48+
IEnumerator IEnumerable.GetEnumerator()
49+
{
50+
return GetEnumerator();
51+
}
52+
}
53+
}

samples/SocketsSample/EndPoints/MessagesEndPoint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace SocketsSample.EndPoints
1313
{
1414
public class MessagesEndPoint : EndPoint
1515
{
16-
public ConnectionList Connections { get; } = new ConnectionList();
16+
private ConnectionList Connections { get; } = new ConnectionList();
1717

1818
public override async Task OnConnectedAsync(ConnectionContext connection)
1919
{

samples/SocketsSample/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void ConfigureServices(IServiceCollection services)
4242
});
4343
});
4444

45-
services.AddEndPoint<MessagesEndPoint>();
45+
services.AddSingleton<MessagesEndPoint>();
4646
}
4747

4848
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

src/Microsoft.AspNetCore.SignalR/HttpConnectionContextExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace Microsoft.AspNetCore.SignalR
88
{
9-
public static class HttpConnectionContextExtensions
9+
public static class DefaultConnectionContextExtensions
1010
{
1111
public static HttpContext GetHttpContext(this HubConnectionContext connection)
1212
{

src/Microsoft.AspNetCore.Sockets/ConnectionBuilderExtensions.cs renamed to src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionBuilderExtensions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using Microsoft.AspNetCore.Protocols;
5-
using Microsoft.Extensions.DependencyInjection;
66

77
namespace Microsoft.AspNetCore.Sockets
88
{
99
public static class ConnectionBuilderExtensions
1010
{
1111
public static IConnectionBuilder UseEndPoint<TEndPoint>(this IConnectionBuilder connectionBuilder) where TEndPoint : EndPoint
1212
{
13-
var endpoint = connectionBuilder.ApplicationServices.GetRequiredService<TEndPoint>();
13+
var endpoint = (TEndPoint)connectionBuilder.ApplicationServices.GetService(typeof(TEndPoint));
14+
15+
if (endpoint == null)
16+
{
17+
throw new InvalidOperationException($"{nameof(EndPoint)} type {typeof(TEndPoint)} is not registered.");
18+
}
1419
// This is a terminal middleware, so there's no need to use the 'next' parameter
1520
return connectionBuilder.Run(connection => endpoint.OnConnectedAsync(connection));
1621
}

src/Microsoft.AspNetCore.Sockets/DefaultConnectionContext.cs renamed to src/Microsoft.AspNetCore.Sockets.Abstractions/DefaultConnectionContext.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
using Microsoft.AspNetCore.Http.Features;
1111
using Microsoft.AspNetCore.Protocols;
1212
using Microsoft.AspNetCore.Protocols.Features;
13-
using Microsoft.Extensions.Internal;
1413

1514
namespace Microsoft.AspNetCore.Sockets
1615
{
@@ -27,7 +26,6 @@ public class DefaultConnectionContext : ConnectionContext,
2726
// This tcs exists so that multiple calls to DisposeAsync all wait asynchronously
2827
// on the same task
2928
private TaskCompletionSource<object> _disposeTcs = new TaskCompletionSource<object>();
30-
internal ValueStopwatch ConnectionTimer { get; set; }
3129

3230
public DefaultConnectionContext(string id, IDuplexPipe transport, IDuplexPipe application)
3331
{

src/Microsoft.AspNetCore.Sockets/ConnectionManager.cs renamed to src/Microsoft.AspNetCore.Sockets.Http/ConnectionManager.cs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class ConnectionManager
2222
// TODO: Consider making this configurable? At least for testing?
2323
private static readonly TimeSpan _heartbeatTickRate = TimeSpan.FromSeconds(1);
2424

25-
private readonly ConcurrentDictionary<string, DefaultConnectionContext> _connections = new ConcurrentDictionary<string, DefaultConnectionContext>();
25+
private readonly ConcurrentDictionary<string, (DefaultConnectionContext Connection, ValueStopwatch Timer)> _connections = new ConcurrentDictionary<string, (DefaultConnectionContext Connection, ValueStopwatch Timer)>();
2626
private Timer _timer;
2727
private readonly ILogger<ConnectionManager> _logger;
2828
private object _executionLock = new object();
@@ -53,7 +53,14 @@ public void Start()
5353

5454
public bool TryGetConnection(string id, out DefaultConnectionContext connection)
5555
{
56-
return _connections.TryGetValue(id, out connection);
56+
connection = null;
57+
58+
if (_connections.TryGetValue(id, out var pair))
59+
{
60+
connection = pair.Connection;
61+
return true;
62+
}
63+
return false;
5764
}
5865

5966
public DefaultConnectionContext CreateConnection(PipeOptions transportPipeOptions, PipeOptions appPipeOptions)
@@ -65,9 +72,8 @@ public DefaultConnectionContext CreateConnection(PipeOptions transportPipeOption
6572
var pair = DuplexPipe.CreateConnectionPair(transportPipeOptions, appPipeOptions);
6673

6774
var connection = new DefaultConnectionContext(id, pair.Application, pair.Transport);
68-
connection.ConnectionTimer = connectionTimer;
6975

70-
_connections.TryAdd(id, connection);
76+
_connections.TryAdd(id, (connection, connectionTimer));
7177
return connection;
7278
}
7379

@@ -78,10 +84,10 @@ public DefaultConnectionContext CreateConnection()
7884

7985
public void RemoveConnection(string id)
8086
{
81-
if (_connections.TryRemove(id, out var connection))
87+
if (_connections.TryRemove(id, out var pair))
8288
{
8389
// Remove the connection completely
84-
SocketEventSource.Log.ConnectionStop(id, connection.ConnectionTimer);
90+
SocketEventSource.Log.ConnectionStop(id, pair.Timer);
8591
_logger.RemovedConnection(id);
8692
}
8793
}
@@ -128,33 +134,34 @@ public void Scan()
128134
{
129135
var status = DefaultConnectionContext.ConnectionStatus.Inactive;
130136
var lastSeenUtc = DateTimeOffset.UtcNow;
137+
var connection = c.Value.Connection;
131138

132139
try
133140
{
134-
c.Value.Lock.Wait();
141+
connection.Lock.Wait();
135142

136143
// Capture the connection state
137-
status = c.Value.Status;
144+
status = connection.Status;
138145

139-
lastSeenUtc = c.Value.LastSeenUtc;
146+
lastSeenUtc = connection.LastSeenUtc;
140147
}
141148
finally
142149
{
143-
c.Value.Lock.Release();
150+
connection.Lock.Release();
144151
}
145152

146153
// Once the decision has been made to dispose we don't check the status again
147154
// But don't clean up connections while the debugger is attached.
148155
if (!Debugger.IsAttached && status == DefaultConnectionContext.ConnectionStatus.Inactive && (DateTimeOffset.UtcNow - lastSeenUtc).TotalSeconds > 5)
149156
{
150-
_logger.ConnectionTimedOut(c.Value.ConnectionId);
151-
SocketEventSource.Log.ConnectionTimedOut(c.Value.ConnectionId);
152-
var ignore = DisposeAndRemoveAsync(c.Value);
157+
_logger.ConnectionTimedOut(connection.ConnectionId);
158+
SocketEventSource.Log.ConnectionTimedOut(connection.ConnectionId);
159+
var ignore = DisposeAndRemoveAsync(connection);
153160
}
154161
else
155162
{
156163
// Tick the heartbeat, if the connection is still active
157-
c.Value.TickHeartbeat();
164+
connection.TickHeartbeat();
158165
}
159166
}
160167

@@ -191,7 +198,7 @@ public void CloseConnections()
191198

192199
foreach (var c in _connections)
193200
{
194-
tasks.Add(DisposeAndRemoveAsync(c.Value));
201+
tasks.Add(DisposeAndRemoveAsync(c.Value.Connection));
195202
}
196203

197204
Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(5));

src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionContextExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Microsoft.AspNetCore.Sockets
99
{
10-
public static class HttpConnectionContextExtensions
10+
public static class DefaultConnectionContextExtensions
1111
{
1212
public static HttpContext GetHttpContext(this ConnectionContext connection)
1313
{

src/Microsoft.AspNetCore.Sockets.Http/Microsoft.AspNetCore.Sockets.Http.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
</ItemGroup>
1313

1414
<ItemGroup>
15-
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
1615
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Common.Http\Microsoft.AspNetCore.Sockets.Common.Http.csproj" />
16+
<ProjectReference Include="..\Microsoft.AspNetCore.Sockets.Abstractions\Microsoft.AspNetCore.Sockets.Abstractions.csproj" />
1717
</ItemGroup>
1818

1919
<ItemGroup>
@@ -22,6 +22,7 @@
2222
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(MicrosoftAspNetCoreRoutingPackageVersion)" />
2323
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="$(MicrosoftAspNetCoreWebSocketsPackageVersion)" />
2424
<PackageReference Include="Microsoft.Extensions.SecurityHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsSecurityHelperSourcesPackageVersion)" />
25+
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" PrivateAssets="All" />
2526
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
2627
</ItemGroup>
2728

src/Microsoft.AspNetCore.Sockets.Http/SocketsDependencyInjectionExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ public static IServiceCollection AddSockets(this IServiceCollection services)
1313
services.AddRouting();
1414
services.AddAuthorizationPolicyEvaluator();
1515
services.TryAddSingleton<HttpConnectionDispatcher>();
16-
return services.AddSocketsCore();
16+
services.TryAddSingleton<ConnectionManager>();
17+
return services;
1718
}
1819
}
1920
}

src/Microsoft.AspNetCore.Sockets/EndPointDependencyInjectionExtensions.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/Microsoft.AspNetCore.Sockets/Microsoft.AspNetCore.Sockets.csproj

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)