Reject a second live WebSocket for the same session name.

Two tabs with the cookie already set never POST /api/session, so name-online on login did not cover the design rule. Claim the name under the same lock as the online check.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 11:04:56 +03:00
co-authored by Cursor
parent d3396b5b8f
commit 1c3ae9ab7e
7 changed files with 219 additions and 6 deletions
+10 -1
View File
@@ -23,7 +23,6 @@ internal sealed class GameSocketHandler(
public async Task HandleAsync(WebSocket socket, string userName, CancellationToken cancellationToken)
{
var client = clients.Add(socket);
client.SetUserName(userName);
var buffer = ArrayPool<byte>.Shared.Rent(ProtocolConstants.MaxMessageSize);
using var connectionCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
@@ -32,6 +31,16 @@ internal sealed class GameSocketHandler(
try
{
if (!clients.TryClaimUserName(client, userName))
{
await CloseAsync(
socket,
WebSocketCloseStatus.PolicyViolation,
"Name is already online.",
cancellationToken).ConfigureAwait(false);
return;
}
using var handshakeCts = CancellationTokenSource.CreateLinkedTokenSource(connectionCts.Token);
handshakeCts.CancelAfter(HandshakeTimeout);