playsocketjs 1.1.9 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/playsocket-client.js +2 -1
- package/dist/playsocket-server.js +34 -26
- package/package.json +1 -1
|
@@ -2333,7 +2333,8 @@ class PlaySocket {
|
|
|
2333
2333
|
* @private
|
|
2334
2334
|
*/
|
|
2335
2335
|
async #attemptReconnect() {
|
|
2336
|
-
|
|
2336
|
+
this.#reconnectCount++;
|
|
2337
|
+
if (this.#reconnectCount > 9) {
|
|
2337
2338
|
this.#triggerEvent("error", "Disconnected from server.");
|
|
2338
2339
|
return this.destroy();
|
|
2339
2340
|
}
|
|
@@ -2226,6 +2226,7 @@ function requireServer () {
|
|
|
2226
2226
|
|
|
2227
2227
|
// Set up ws event handlers
|
|
2228
2228
|
this.#wss.on('connection', ws => {
|
|
2229
|
+
ws.connectionId = crypto.randomUUID();
|
|
2229
2230
|
ws.isAlive = true;
|
|
2230
2231
|
ws.on('pong', () => { ws.isAlive = true; });
|
|
2231
2232
|
ws.on('message', msg => this.#handleMessage(ws, msg));
|
|
@@ -2258,9 +2259,14 @@ function requireServer () {
|
|
|
2258
2259
|
try {
|
|
2259
2260
|
const data = decode(message);
|
|
2260
2261
|
|
|
2261
|
-
// Apply rate limiting
|
|
2262
|
-
if (
|
|
2263
|
-
|
|
2262
|
+
// Apply rate limiting to all connections (including unregistered)
|
|
2263
|
+
if (!this.#checkRateLimit(ws.connectionId, data.type)) {
|
|
2264
|
+
ws.rateLimitViolations = (ws.rateLimitViolations || 0) + 1;
|
|
2265
|
+
if (ws.rateLimitViolations > 5) {
|
|
2266
|
+
ws.terminate();
|
|
2267
|
+
return console.error(`Connection ${ws.connectionId} terminated due to repeated rate limit violations.`);
|
|
2268
|
+
}
|
|
2269
|
+
return console.error(`Connection ${ws.connectionId} rate limit exceeded.`);
|
|
2264
2270
|
}
|
|
2265
2271
|
|
|
2266
2272
|
switch (data.type) {
|
|
@@ -2465,24 +2471,24 @@ function requireServer () {
|
|
|
2465
2471
|
* Check rate limit using token bucket algorithm
|
|
2466
2472
|
* @private
|
|
2467
2473
|
*/
|
|
2468
|
-
#checkRateLimit(
|
|
2469
|
-
const MAX_POINTS =
|
|
2474
|
+
#checkRateLimit(connectionId, operationType) {
|
|
2475
|
+
const MAX_POINTS = 20;
|
|
2470
2476
|
const now = Date.now();
|
|
2471
2477
|
|
|
2472
|
-
if (!this.#rateLimits.has(
|
|
2473
|
-
this.#rateLimits.set(
|
|
2478
|
+
if (!this.#rateLimits.has(connectionId)) {
|
|
2479
|
+
this.#rateLimits.set(connectionId, { points: MAX_POINTS, lastReset: now });
|
|
2474
2480
|
return true;
|
|
2475
2481
|
}
|
|
2476
2482
|
|
|
2477
|
-
const limit = this.#rateLimits.get(
|
|
2483
|
+
const limit = this.#rateLimits.get(connectionId);
|
|
2478
2484
|
|
|
2479
|
-
// Reset points if interval has passed (
|
|
2480
|
-
if (now - limit.lastReset >
|
|
2485
|
+
// Reset points if interval has passed (1s)
|
|
2486
|
+
if (now - limit.lastReset > 1000) {
|
|
2481
2487
|
limit.points = MAX_POINTS;
|
|
2482
2488
|
limit.lastReset = now;
|
|
2483
2489
|
}
|
|
2484
2490
|
|
|
2485
|
-
const pointCost = ['create_room', 'join_room'].includes(operationType) ?
|
|
2491
|
+
const pointCost = ['create_room', 'join_room'].includes(operationType) ? 5 : 1;
|
|
2486
2492
|
if (limit.points < pointCost) return false;
|
|
2487
2493
|
|
|
2488
2494
|
limit.points -= pointCost;
|
|
@@ -2494,22 +2500,25 @@ function requireServer () {
|
|
|
2494
2500
|
* @private
|
|
2495
2501
|
*/
|
|
2496
2502
|
#handleDisconnection(ws) {
|
|
2497
|
-
|
|
2498
|
-
this.#clients.delete(ws.clientId); // Immediately remove from active clients (otherwise, server would try to message this client)
|
|
2503
|
+
this.#rateLimits.delete(ws.connectionId);
|
|
2499
2504
|
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
if (roomId != null) this.#changeHostIfDisconnected(roomId, ws.clientId);
|
|
2505
|
+
if (ws.clientId) {
|
|
2506
|
+
this.#clients.delete(ws.clientId); // Immediately remove from active clients (otherwise, server would try to message this client)
|
|
2503
2507
|
|
|
2504
|
-
|
|
2505
|
-
this.#
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2508
|
+
// If client was in a room, check if they were the host & migrate
|
|
2509
|
+
const roomId = this.#clientRooms.get(ws.clientId);
|
|
2510
|
+
if (roomId != null) this.#changeHostIfDisconnected(roomId, ws.clientId);
|
|
2511
|
+
|
|
2512
|
+
if (ws.willfulDisconnect) {
|
|
2513
|
+
this.#disconnectClient(ws); // Immediate disconnection
|
|
2514
|
+
} else {
|
|
2515
|
+
// Pending complete disconnection with 5s grace period to allow for reconnections
|
|
2516
|
+
this.#pendingDisconnects.set(ws.clientId, {
|
|
2517
|
+
timeout: setTimeout(() => {
|
|
2518
|
+
this.#disconnectClient(ws);
|
|
2519
|
+
}, 5000)
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2513
2522
|
}
|
|
2514
2523
|
}
|
|
2515
2524
|
|
|
@@ -2520,7 +2529,6 @@ function requireServer () {
|
|
|
2520
2529
|
*/
|
|
2521
2530
|
#disconnectClient(ws) {
|
|
2522
2531
|
this.#pendingDisconnects.delete(ws.clientId);
|
|
2523
|
-
this.#rateLimits.delete(ws.clientId);
|
|
2524
2532
|
this.#clientTokens.delete(ws.clientId);
|
|
2525
2533
|
const roomId = this.#clientRooms.get(ws.clientId);
|
|
2526
2534
|
const room = this.#rooms[roomId];
|