Skip to content

[mod_sofia] Fix BroadSoft SCA line-seize clobbering between devices - #3232

Open
lodperera wants to merge 1 commit into
signalwire:masterfrom
lodperera:fix-sca-line-seize-per-device
Open

lodperera wants to merge 1 commit into
signalwire:masterfrom
lodperera:fix-sca-line-seize-per-device

Conversation

@lodperera

Copy link
Copy Markdown

Problem

With manage-shared-appearance=true, a line-seize SUBSCRIBE from one device deletes every seized row for the shared line before inserting its own (sofia_presence_handle_sip_i_subscribe). With two or more phones on one shared line:

  • each seize or seize refresh (Yealink refreshes about every 6 s) wipes the other phones' seizes, so the appearance LEDs flip between phones;
  • releasing a seize (Expires: 0) also clears seizes held by other phones;
  • a seize for an appearance already in use by another device is never refused;
  • any call-state change (sync_sla() with clear=true) clears all seizes on the line.

Also fixes the event='line-seized' typo in sync_sla() (a subscription is never stored with that event name).

Change

  • Store the line-seize subscription Call-ID in sip_dialogs.call_id, so each seize row has an owner.
  • Seize refresh/release only remove the subscriber's own seize row (plus legacy rows with no owner, and expired rows).
  • Refuse a line-seize with 480 Temporarily Unavailable if the requested appearance is held by another device's unexpired seize or by an active call.
  • On call-state changes, only clear seizes that are expired or whose appearance is now used by a call.

No schema change: sip_dialogs.call_id already exists. Single file: src/mod/endpoints/mod_sofia/sofia_presence.c.

Testing

FreeSWITCH 1.11.1 (Debian 12), two Yealink T54W (fw 96.87.0.20) on one shared line:

Scenario Before After
Phone A seizes appearance 1, phone B seizes appearance 2 LEDs flip; each refresh drops the other seize Both seizes kept
B seizes the appearance A holds Accepted, A's seize lost 480 (T54W itself also moves to a free appearance)
A releases its seize B's seize cleared too Only A's seize cleared
Outbound, inbound ring-all, public hold + retrieve from other phone, barge-in, call pull OK OK (no regression)

A scripted SIP client test (two UDP clients sending authenticated line-seize SUBSCRIBEs and checking sip_dialogs) fails 4/6 checks before the change and passes 6/6 after it.

🤖 Generated with Claude Code

https://claude.ai/code/session_017S4mpb5sfS2fgB3E8j2Byi

With manage-shared-appearance enabled, a line-seize from one device deleted
every 'seized' row for the shared line before inserting its own. Two phones
on the same shared line therefore overwrote each other's seize on every
seize refresh (Yealink refreshes about every 6 s), so appearance LEDs flipped
between phones, and releasing a seize also cleared seizes held by others.
A seize for an appearance already in use by another device was never refused.

Changes:
* Store the line-seize subscription Call-ID in sip_dialogs.call_id so each
  seize row has an owner.
* Seize refresh and seize release only remove the subscriber's own seize row
  (plus legacy rows without an owner and expired rows).
* Refuse a line-seize with 480 when the requested appearance is held by
  another device's live seize or by an active call.
* When call state changes, only clear seizes that have expired or whose
  appearance is now used by a call, instead of all seizes on the line.
* Fix the 'line-seized' event name typo in sync_sla().

Tested with two Yealink T54W (fw 96.87.0.20) on one shared line: seize on
different keys, seize race on the same key, outbound, inbound ring-all,
public hold/retrieve, barge-in and call pull all behave correctly. A
scripted SIP test that seizes from two clients reproduces the bug before
the change and passes after it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant