Skip to content

Commit 205fb6c

Browse files
committed
Bump versions to 3.0.1.0 and deprecate WebListenerServer (2.13.1.0)
1 parent b125d57 commit 205fb6c

5 files changed

Lines changed: 121 additions & 13 deletions

File tree

src/WebSocketExtensions.Kestrel/KestrelWebSocketServer.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.Concurrent;
55
using System.Collections.Generic;
6+
using System.Collections.ObjectModel;
67
using System.IO;
78
using System.Linq;
89
using System.Net;
@@ -23,6 +24,8 @@ public record class KestrelWebSocketServerStats(PagingMessageQueueStats QueueSta
2324
public class KestrelWebSocketServer : IDisposable
2425
{
2526
private ConcurrentDictionary<Guid, WebSocket> _clients;
27+
private Dictionary<string, List<Guid>> path_to_clients_map;
28+
2629
private ConcurrentDictionary<string, Func<KestrelWebSocketServerBehavior>> _behaviors;
2730
private PagingMessageQueue _messageQueue = null;
2831
private CancellationTokenSource _cancellationTokenSource = null;
@@ -93,6 +96,25 @@ public IList<Guid> GetActiveConnectionIds()
9396
{
9497
return _clients.Where(c => c.Value.State == WebSocketState.Open).Select(c => c.Key).ToList();
9598
}
99+
public List<WebSocket> GetWebsocketsByPath(string path)
100+
{
101+
if (!path_to_clients_map.TryGetValue(path, out List<Guid> sockets))
102+
return new List<WebSocket>();
103+
104+
105+
var websocks = sockets.Select(s =>
106+
{
107+
WebSocket ws = null;
108+
if (_clients.TryGetValue(s, out ws)
109+
&& ws.State == WebSocketState.Open)
110+
return ws;
111+
return null;
112+
})
113+
.Where(s => s != null)
114+
.ToList();
115+
116+
return websocks;
117+
}
96118

97119
public bool IsListening()
98120
{
@@ -167,6 +189,9 @@ public bool AddRouteBehavior<TBehavior>(string route, Func<TBehavior> p) where T
167189
{
168190
stopListeningThread();
169191

192+
path_to_clients_map = new Dictionary<string, List<Guid>>();
193+
194+
170195
var listenerThredStarted = new TaskCompletionSource<bool>();
171196

172197
_cancellationTokenSource = new CancellationTokenSource();
@@ -196,7 +221,17 @@ public bool AddRouteBehavior<TBehavior>(string route, Func<TBehavior> p) where T
196221
Func<KestrelWebSocketServerBehavior> builder = null;
197222
if (_behaviors.TryGetValue(context.Request.Path, out builder))
198223
{
199-
await handleClient(context, builder, _cancellationTokenSource.Token);
224+
List<Guid> sockets = null;
225+
if (!path_to_clients_map.ContainsKey(context.Request.Path))
226+
{
227+
sockets = new List<Guid>();
228+
path_to_clients_map.Add(context.Request.Path, sockets);
229+
}
230+
else
231+
{
232+
sockets = path_to_clients_map[context.Request.Path];
233+
}
234+
await handleClient(context, builder, sockets, _cancellationTokenSource.Token);
200235
}
201236

202237
if (context.Request.Path.HasValue
@@ -268,8 +303,13 @@ public Action<T, T2> MakeSafe<T, T2>(Action<T, T2> torun, string handlerName)
268303
}
269304
};
270305
}
306+
object socketsLock = new object();
271307

272-
private async Task handleClient<TWebSocketBehavior>(HttpContext listenerContext, Func<TWebSocketBehavior> behaviorBuilder, CancellationToken token)
308+
private async Task handleClient<TWebSocketBehavior>(
309+
HttpContext listenerContext,
310+
Func<TWebSocketBehavior> behaviorBuilder,
311+
List<Guid> sockets,
312+
CancellationToken token)
273313
where TWebSocketBehavior : KestrelWebSocketServerBehavior
274314
{
275315
Guid connectionId;
@@ -314,6 +354,11 @@ private async Task handleClient<TWebSocketBehavior>(HttpContext listenerContext,
314354

315355
var safeconnected = MakeSafe<Guid, HttpContext>(behavior.OnConnectionEstablished, "behavior.OnClientConnected");
316356
safeconnected(connectionId, listenerContext);
357+
lock (socketsLock)
358+
{
359+
sockets.Add(connectionId);
360+
}
361+
317362
}
318363
catch (Exception e)
319364
{
@@ -350,6 +395,10 @@ private async Task handleClient<TWebSocketBehavior>(HttpContext listenerContext,
350395

351396
webSocket?.CleanupSendMutex();
352397
listenerContext.Abort();
398+
lock (socketsLock)
399+
{
400+
sockets.Remove(connectionId);
401+
}
353402

354403
bool clientRemoved = _clients.TryRemove(connectionId, out webSocket);
355404
if (clientRemoved)

src/WebSocketExtensions.Kestrel/WebSocketExtensions.Kestrel.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
<RepositoryUrl>https://github.com/maxfridbe/websocketextensions</RepositoryUrl>
1616
<RepositoryType>git</RepositoryType>
1717
<PackageReleaseNotes>Feel free to contribute, Integration Tests Work but no other gaurentees.</PackageReleaseNotes>
18-
<Version>3.0.0.0</Version>
19-
<AssemblyVersion>3.0.0.0</AssemblyVersion>
20-
<FileVersion>3.0.0.0</FileVersion>
18+
<Version>3.0.1.0</Version>
19+
<AssemblyVersion>3.0.1.0</AssemblyVersion>
20+
<FileVersion>3.0.1.0</FileVersion>
2121
<IncludeSymbols>true</IncludeSymbols>
2222
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
2323
</PropertyGroup>

src/WebSocketExtensions.Tests/IntegrationTests_Kestrel.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,65 @@ public async Task TestCreateServer_connect_recv_echo()
211211

212212
}
213213

214+
[Fact]
215+
public async Task TestGetWebsocketsByPath()
216+
{
217+
//arrange
218+
var logger = _loggerFac();
219+
using var server = new KestrelWebSocketServer(logger);
220+
var port = _FreeTcpPort();
221+
222+
server.AddRouteBehavior("/aaa", () => new testBeh());
223+
server.AddRouteBehavior("/bbb", () => new testBeh());
224+
await server.StartAsync($"http://localhost:{port}/");
225+
226+
using var client1 = new WebSocketClient();
227+
await client1.ConnectAsync($"ws://localhost:{port}/aaa");
228+
229+
using var client2 = new WebSocketClient();
230+
await client2.ConnectAsync($"ws://localhost:{port}/aaa");
231+
232+
using var client3 = new WebSocketClient();
233+
await client3.ConnectAsync($"ws://localhost:{port}/bbb");
234+
235+
//act
236+
var aaaSockets = server.GetWebsocketsByPath("/aaa");
237+
var bbbSockets = server.GetWebsocketsByPath("/bbb");
238+
var cccSockets = server.GetWebsocketsByPath("/ccc");
239+
240+
//assert
241+
Assert.Equal(2, aaaSockets.Count);
242+
Assert.Equal(1, bbbSockets.Count);
243+
Assert.Empty(cccSockets);
244+
}
245+
246+
[Fact]
247+
public async Task TestGetWebsocketsByPath_AfterDisconnect()
248+
{
249+
//arrange
250+
var logger = _loggerFac();
251+
using var server = new KestrelWebSocketServer(logger);
252+
var port = _FreeTcpPort();
253+
254+
server.AddRouteBehavior("/aaa", () => new testBeh());
255+
await server.StartAsync($"http://localhost:{port}/");
256+
257+
using var client1 = new WebSocketClient();
258+
await client1.ConnectAsync($"ws://localhost:{port}/aaa");
259+
260+
using (var client2 = new WebSocketClient())
261+
{
262+
await client2.ConnectAsync($"ws://localhost:{port}/aaa");
263+
Assert.Equal(2, server.GetWebsocketsByPath("/aaa").Count);
264+
}
265+
266+
//act
267+
await Task.Delay(200); // Wait for server to process disconnect
268+
var aaaSockets = server.GetWebsocketsByPath("/aaa");
269+
270+
//assert
271+
Assert.Single(aaaSockets);
272+
}
214273

215274
[Fact]
216275
public async Task TestCreateServer_connect_ping()

src/WebSocketExtensions.WebListenerServer/WebSocketExtensions.WebListenerServer.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;net8.0</TargetFrameworks>
44
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0;net472;net48;net8.0</TargetFrameworks>
55
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
6-
<Description>A WebSocketClient and WebSocketServer wrapper for WebSocket Api In System.Net, A drop in replacement for WebSocketSharp, Has implementations using HttpListener, Weblistener moved to its own obsolete package</Description>
6+
<Description>DEPRECATED: Use KestrelWebSocketServer. A WebSocketClient and WebSocketServer wrapper for WebSocket Api In System.Net, A drop in replacement for WebSocketSharp, Has implementations using HttpListener, Weblistener moved to its own obsolete package</Description>
77
<Authors>Max Fridberg</Authors>
88
<Company />
99
<obsolete>The package this relys on is no longer maintained</obsolete>
@@ -13,10 +13,10 @@
1313
<PackageIconUrl>https://raw.githubusercontent.com/maxfridbe/websocketextensions/master/websocket.png</PackageIconUrl>
1414
<RepositoryUrl>https://github.com/maxfridbe/websocketextensions</RepositoryUrl>
1515
<RepositoryType>git</RepositoryType>
16-
<PackageReleaseNotes>Feel free to contribute, Integration Tests Work but no other gaurentees.</PackageReleaseNotes>
17-
<Version>2.13.0.0</Version>
18-
<AssemblyVersion>2.13.0.0</AssemblyVersion>
19-
<FileVersion>2.13.0.0</FileVersion>
16+
<PackageReleaseNotes>DEPRECATED: Use KestrelWebSocketServer. This package is no longer maintained.</PackageReleaseNotes>
17+
<Version>2.13.1.0</Version>
18+
<AssemblyVersion>2.13.1.0</AssemblyVersion>
19+
<FileVersion>2.13.1.0</FileVersion>
2020
<IncludeSymbols>true</IncludeSymbols>
2121
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
2222
</PropertyGroup>

src/WebSocketExtensions/WebSocketExtensions.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
<RepositoryUrl>https://github.com/maxfridbe/websocketextensions</RepositoryUrl>
1515
<RepositoryType>git</RepositoryType>
1616
<PackageReleaseNotes>Feel free to contribute, Integration Tests Work but no other gaurentees.</PackageReleaseNotes>
17-
<Version>3.0.0.0</Version>
18-
<AssemblyVersion>3.0.0.0</AssemblyVersion>
19-
<FileVersion>3.0.0.0</FileVersion>
17+
<Version>3.0.1.0</Version>
18+
<AssemblyVersion>3.0.1.0</AssemblyVersion>
19+
<FileVersion>3.0.1.0</FileVersion>
2020
<IncludeSymbols>true</IncludeSymbols>
2121
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
2222
</PropertyGroup>

0 commit comments

Comments
 (0)