Skip to content

WebSocket rooms: no rate limit on broadcast — one client can starve every worker's mailbox #120

Description

@EdmondDantes

Follow-up to #2 (cross-worker rooms). Not a regression — a limit was never in the design.

What

WebSocketRoom::broadcast() hands one command per worker to that worker's mailbox (thread_mailbox_t, capacity 4096). Nothing bounds how often a connection may broadcast, and nothing separates one room's traffic from another's: every room in the process shares the same per-worker inbox.

So a single client looping on a message that the handler relays with broadcast() fills every other worker's inbox. Once an inbox is full, thread_mailbox_post() fails and the message is dropped — including messages from other rooms and other tenants. Availability damage is process-wide, not confined to the abusive room.

Current behaviour

  • Overflow is no longer silent (fixed in 7485dbd): drops are counted, readable via ws_hub_dropped().
  • But there is still no counter-measure — the traffic is simply lost, and the sender gets no signal (broadcast() returns members served on the calling worker, which the flood does not affect).

Why it matters

The room API is the one WebSocket surface where an unprivileged peer can cause work on every worker in the process with a single frame. send()/trySend() only ever touch the peer's own connection, and the outbound FIFO is already capped per session (1013 close on overflow). Rooms have no equivalent.

Possible directions (not decided)

  • Per-connection broadcast rate limit / token bucket, with a knob on HttpServerConfig (setWsBroadcastRateLimit()), mirroring how the other WS limits are exposed as setters.
  • Per-room fair queueing, so one hot room cannot evict another's commands.
  • Backpressure instead of drop: let broadcast() report that the fan-out could not be queued, so a handler can slow down (it must stay non-suspending, so this would be a return value, not a park).
  • Surface ws_hub_dropped() in the server stats so an operator can see it happening before users report it.

Notes

  • Discovered during the review that produced 7485dbd; the drop counter landed there, the limit did not.
  • WS_HUB_MAILBOX_CAPACITY = 4096 (src/websocket/ws_hub.c).

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingenhancementNew feature or request

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions