Skip to content

Blog

Two bugs only a phone left on for days could show

· Sipral

A test call lasts seconds and a lab run lasts an hour. A phone stays on for days, sleeps, wakes, changes network and keeps a few subscriptions open the whole time. Two bugs in Sipral lived only in that space. We found the first because a phone ran into it. The second showed up when we pointed the lab at an older Asterisk.

A phone that stopped taking calls

On 12 October a phone running Sipral refused every call, in and out. It had been running for four days and had changed network about 68 times. Restarting the app fixed it.

The phone watched seven colleagues’ busy lamps. Each lamp is a SIP subscription, and each subscription holds a dialog. When the phone wakes or moves to another network, Sipral can’t trust its old subscriptions, so it starts each one again under a new Call-ID. It did start them again, but it never closed the old dialogs. Every wake left seven dead dialogs behind, and a stack keeps at most 128 by default. After about eighteen wakes the limit was full. From then on every call the phone placed failed with LimitReached, and every call offered to it was answered 503.

Now, when a subscription starts again, Sipral closes the old dialog first. A test now runs a stack with a limit of three dialogs through ten wakes and then places a call. Without the fix, that call fails. The fix shipped in 1.2.0.

A voicemail lamp that never moved

On 15 October the lab ran its flows against the Asterisk 18 inside a ViciBox, which still uses the older chan_sip driver, as some older FreePBX systems still do. Every flow passed except message waiting. The mailbox’s count arrived once, when the subscription started, and never changed after that, however many messages were left.

chan_sip sends each NOTIFY of a subscription under the same Via branch. RFC 3261 says a new request should carry a new branch, and Sipral matched requests on the branch alone. So it took the second NOTIFY, the one carrying the new count, for a resend of the first, and answered it with the first one’s 200 OK. chan_sip refused that answer and kept sending the NOTIFY until the subscription ended. The count never got through.

Now every request except INVITE is matched on its CSeq number as well as its branch. A real resend repeats the CSeq, and a new request moves it on. Message waiting now passes on the ViciBox, and on FusionPBX too. The fix is on main and goes out in the next release. It should also help busy lamps on PBXs that still run chan_sip, since those arrive the same way.

Why we write these up

Neither bug was in a rare corner. Every phone wakes, and every older Asterisk sends its NOTIFYs this way. Both stayed hidden because they need time, or a server we hadn’t tested yet. Each one now has a test that fails without its fix, and the lab keeps adding servers so the next one turns up there instead of on someone’s desk. What changed is in the changelog.