[Bug]: maxClients not (fully) respected
hunkydoryrepair opened this issue · comments
Context
We had 1500 players in one room, when maxClients was set to 1000. With so many clients, they are constantly leaving and entering.
Bug description
maxClients is not strictly enforced.
There is a small window for a flaw, allowing more clients to connect to a room than strictly allowed.
I believe this sequence is due to the await onAsync
call in _onJoin.
Note: the reservedSeat
is cleared before await onAsync
is called, and the client is added to the this.clients
only AFTER onAsync is called. This leaves a brief moment (however long onAsync takes) where the client count is off by 1 when hasReachedMaxClients
is called.
I notice that reserveSeat
is also deleted in the finally
clause later. Since it is deleted above, this should never do anything, but perhaps the intention was to delete it only after the client is added to the clients.
Some other aspects that may exacerbate this:
- when a client leaves, there is no check for hasReachedMaxClients, so room will be unlocked even if maxclients exceeds count. This will only make the room appear available when it really is not.
- _reserveSeat doesn't check if room is locked. Since the room is not unlocked in the "gap" discussed, if the room was actually locked and CHECKED then _reserveSeat would not allow more clients, even though the count is < max. When requests are sent from multiple servers at once, even though the first one may lock the room, the subsequent ones may still go through and the previous requests are causing room count to drop below the max.
Reproduction
No response
Steps to reproduce
- use async onAuth that takes a long time to complete (30 seconds +)
- set maxClients to a low number on the room (2)
- sequentially add clients, pausing briefly between each (long enough to enter onAuth). Each client will enter onAuth and wait, and the room count (as calculated in hasReachedMaxClients) will be 0, allowing another client to start the process without locking the room.
Environment & Versions
Colyseus: 0.15.15
I think proper fix would be to only remove reservedSeat AFTER client is added to clients
array, in the finally
for the non-reconnection case, and just after the add for the reconnection case.
Thank you for reporting and for the suggestion @hunkydoryrepair, it turns out the first delete
operation was there by mistake - as it is already deleted on the other final code branches (reconnection at cleanup, and at the finally block)
turns out other tests are failing after this, pls don't upgrade, I'm on it 🥵
properly fixed now on @colyseus/core
version 0.15.22
🙌