mirror of
https://github.com/coturn/coturn.git
synced 2026-10-24 00:08:57 +03:00
Under --mobility a resume does not hard-switch the allocation onto the new client path; it opens a dual-5-tuple transition and links the resuming session to the allocation via a single backlink (mobile_pending_resume). An authenticated user could resume one allocation repeatedly from fresh 5-tuples without completing any handoff: each resume disarmed the new session's un-allocated watchdog and overwrote that single backlink, orphaning the previous pending session. Orphans were unreachable by the transition-deadline sweep and owned no allocation timer, so they stayed allocated indefinitely, letting one user grow server memory without bound. --user-quota did not stop it, since pending sessions hold no quota unit. Enforce one pending resume per allocation: - mobile_begin_transition() fully tears down the existing pending session before opening a new one. It runs in REFRESH packet context, so the shutdown is synchronous and also clears the allocation's backlink via shutdown's transition-unlink path. - mobile_abort_transition() re-arms the disarmed watchdog so an abandoned pending left after the transition deadline is reaped from timer context (safe during the session-map sweep, which only schedules the timer). - mobile_complete_transition() promotes only when the session is still the allocation's current pending resume, so a superseded pending can neither clear live transition state nor steal a socket move. Add examples/run_tests_mobility_resume_flood.sh (+ raw-STUN driver scripts/mobility_resume_flood.py): it floods chained resumes and asserts every superseded pending is torn down. It passes on the fixed server and fails on the unpatched one. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>