mirror of
https://github.com/livekit/livekit.git
synced 2026-08-15 15:39:49 +00:00
* Add per-participant concurrent TURN allocation quota The embedded TURN server authenticated each Allocate request but placed no cap on how many relay allocations a single participant credential could hold. One participant could reuse its credential across many client 5-tuples and open one relay socket/port per request, exhausting the shared relay-port range for everyone else. Add a configurable per-participant limit (turn.per_user_relay_allocation_limit, default 4) wired to Pion's QuotaHandler, keyed by the participant ID from HandleAuth. Slots are reserved before allocation and released when the allocation ends, under a single lock, so concurrent Allocate bursts cannot race past the limit; reservations are keyed by source address so retransmits are idempotent. Over-quota requests receive 486 (Allocation Quota Reached). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Reclaim unconfirmed TURN allocation reservations Allow reserved a quota slot before Pion built the relay, but the slot was only released on the allocation-deleted event. An Allocate that passed the quota check and then failed to create a relay (e.g. relay-port range exhausted) emits no event, so the reservation leaked: after enough failures a participant could lock itself out with 486, and the tracking map grew without bound. Reservations now start pending and are confirmed on allocation-created; each pending reservation carries a reclaim timer that frees the slot after a TTL, so a failed attempt cannot hold a slot forever while concurrent-burst safety is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Make TURN reservation reclaim identity-aware The reclaim timer captured only userID+key. Because Timer.Stop cannot cancel a callback that has already fired and is waiting on the lock, a stale timer could delete a replacement reservation created for the same userID+key after the original was released, leaving a live allocation untracked and letting the participant exceed its cap. reclaimPending now captures the slot pointer and only removes the entry when the map still holds that exact slot, so a stale timer is a no-op. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>