Summary
A presence request ({a: 'pr', ch}) makes every client subscribed to ch re-send all of its non-null local presence. The server publishes the request without any checks: the requester doesn't need to be subscribed to the channel, and no presence middleware runs for it (Agent._requestPresence, and the receiving agents forward it to their clients in _handlePresenceData without going through 'sendPresence').
Each re-sent presence is then an ordinary submission: it goes through 'receivePresence', a transform to the latest doc version for doc presence, and a broadcast through 'sendPresence' to every other subscriber. So one cheap message costs work that grows with the square of the number of subscribers.
Repro
- Subscribe 10 clients to
room, each with one presence
- From an 11th client that isn't subscribed, send
{a: 'pr', ch: 'room'}
- The server handles 10 presence submissions and 90
'sendPresence' deliveries
Sending pr in a loop repeats this indefinitely, on any channel, including doc channels for docs the requester can't read.
Suggested fix
Some combination of:
- Only accept
pr from an agent subscribed to that channel. The only client-side caller, RemoteDocPresence, is already subscribed.
- Throttle re-broadcasts, so a burst of requests on a channel triggers one round of re-sends.
- Run a middleware hook for presence requests, so apps can gate them.
Summary
A presence request (
{a: 'pr', ch}) makes every client subscribed tochre-send all of its non-nulllocal presence. The server publishes the request without any checks: the requester doesn't need to be subscribed to the channel, and no presence middleware runs for it (Agent._requestPresence, and the receiving agents forward it to their clients in_handlePresenceDatawithout going through'sendPresence').Each re-sent presence is then an ordinary submission: it goes through
'receivePresence', a transform to the latest doc version for doc presence, and a broadcast through'sendPresence'to every other subscriber. So one cheap message costs work that grows with the square of the number of subscribers.Repro
room, each with one presence{a: 'pr', ch: 'room'}'sendPresence'deliveriesSending
prin a loop repeats this indefinitely, on any channel, including doc channels for docs the requester can't read.Suggested fix
Some combination of:
prfrom an agent subscribed to that channel. The only client-side caller,RemoteDocPresence, is already subscribed.