
The BLF support (or dialog-info) is a highly useful feature in Class 5 switches (or PBXes). BLF is more than a lit led on your phone, letting you know if a party is engaged in a call or not. The BLF, as a mechanism of sharing the status of the parties and their calls, is required for building other complex Class 5 features. For example, in Call Pickup, you can see more than the fact that there is an incoming call to a certain extension, you can see who is the caller. Or, in Call Parking, you can see list of the parked calls and which are the other parties in those call.
Shortly said, any feature that requires to know the status (or monitor) of the calls and which are the parties involved in that call will require access to the BLF data. So it is essential for a SIP server to provide accurate BLF information.
What was the problem?
In OpenSIPS, the BLF (or dialoginfo) support was added in 2008 and it worked like a charm.

Still, with all the class 5 related work from the past 2-3 years, some limitations popped up. Mainly the inability of the original BLF support to properly generate data for calls with serial or parallel forking. And we had this limitation because:
- the “dialog ID” from BLF level was the same with the SIP Call-ID, so you were not able to differentiate between the BLF events generated by different branches (per forking destination) of the same call.
- the implementation supported only one BLF callee party, so you could not properly publish the BLF events in case of a parallel forking, where you may have multiple ringing callees in the same time. To be more precise, you were not able to “see” that multiple destinations were ringing for that call, you were not able to get events for the callees declining or triggering a timeout for the call, you could not see which was the right callee party answering the call (the published callee information on “answering” was broken).
BLF reloaded
In OpenSIPS 3.1, which is focused on Class 5 related feature, we also addressed these BLF limitations.
More technically said, we re-worked the “pua_dialoginfo” module to get access to the transaction information (not only to the dialog information as befire) – this made the module aware of the multiple branches created, not only dialog aware, so data related to call branches can now be also published.
An important change is how the BLF sessions are mapped over the SIP dialogs. If before we had one BLF session per SIP dialog, now, in 3.1, we have one BLF session for each branch in a SIP dialog/call (note that multiple branches in the same time are possible only in the early stage of a call – once the call is answered, only one branch will remain).
This automatically increased the granularity (or the verbosity) of the generated BLF events, so let’s see the differences.
Serial forking scenario
Let’s have the case of Alice calling Bob. Bob’s device rings and after 20 seconds it is cancelled by OpenSIPS due timeout (no answer). Then the call, via serial forking, is sent to Charlie, who actually answers the call.
With the old implementation we had these events triggered, step by step:
- Alice called Bob and Bob is ringing. These events are generated by the dialog layer:
- ringing( dialog, Alice in relation to Bob)
- ringing( dialog, Bob in relation to Alice)
- Bob times out
- nothing, as this event is not “seen” by the dialog layer
- Call is serial forked to Charlie and Charlie starts to ring
- nothing, as this event is not reported by the dialog layer, as dialog already in ringing
- Charlie answers the call. These events are generated by the dialog level but with the wrong info, as the callee party was not updated (the parties are learned only at INVITE time):
- answered( dialog, Alice in relation to Bob)
- answered( dialog, Bob in relation to Alice)
As you can see, we had missing and also bogus events here :(.
So let’s see how the 3.1 implementation works with this scenario:
- Alice called Bob and Bob is ringing. These events are generated by the transaction layer this time:
- ringing( dialog1, Alice in relation to Bob)
- ringing( dialog1, Bob in relation to Alice)
- Bob times out and the transaction layer reports:
- terminated( dialog1, Alice in relation to Bob)
- terminated( dialog1, Bob in relation to Alice)
- Call is serial forked to Charlie, we use the new dialoginfo_set_branch_callee() script function to update BLF about the new callee; and Charlie starts to ring. The transaction layer reports again, for a new branch:
- ringing( dialog2, Alice in relation to Charlie)
- ringing( dialog2, Charlie in relation to Alice)
- Charlie answers the call and the dialog layer reports:
- answered( dialog2, Alice in relation to Charlie)
- answered( dialog2, Charlie in relation to Alice)
Besides the higher and more accurate volume of event (accurately describing the call progress), note that correct/updated report of the parties involved in the call and also that each branch is reported as a separate BLF session/dialog, so you can actually understand what happened with the call (you had a first failed call attempt and then a second successful call attempt).
Parallel forking scenario
Now let’s see the differences when comes to the parallel call forking scenario, like in the case of a parallel Hunt Group.
We have Alice calling Bob and Charlie in the same time. Bob declines the call while Charlie is finally picking up the call and talks to Alice.
With the old implementation we had these events triggered, step by step:
- Alice calls Bob and Charlie, both are ringing. In branch_route we use the new dialoginfo_set_branch_callee() script function to set the callee for each branch. These events are generated by the dialog layer:
- ringing( dialog, Alice in relation to Bob)
- ringing( dialog, Bob in relation to Alice)
- nothing is reported about Charlie, as Charlie is not known – only one callee is supported.
- Bob rejects the call
- nothing, as this event is not “seen” by the dialog layer
- Charlie answers the call. These events are generated by the dialog level but with the wrong info, as the correct callee party is not known by the module :
- answered( dialog, Alice in relation to Bob)
- answered( dialog, Bob in relation to Alice)
As you can see, we had one missing event, and also a bogus one here :(.
So let’s see if the 3.1 implementation can do better with this scenario:
- Alice calls Bob and Charlie and both are ringing. These events are generated by the transaction layer this time:
- ringing( dialog1, Alice in relation to Bob)
- ringing( dialog1, Bob in relation to Alice)
- ringing( dialog2, Alice in relation to Charlie)
- ringing( dialog2, Charlie in relation to Alice)
- Bob rejects the call and the transaction layer reports:
- terminated( dialog1, Alice in relation to Bob)
- terminated( dialog1, Bob in relation to Alice)
- Charlie answers the call and the dialog layer reports:
- answered( dialog2, Alice in relation to Charlie)
- answered( dialog2, Charlie in relation to Alice)
Again, a wider and more accurate set of events are automatically reported by the module.
Conclusions
The new BLF implementation has two major advantages:
- it is able to expose events related to call forking (prior to call answering). This will provide a more accurate insight of the call genesis.
- it correctly reports the callee party, both in serial forking (when the callee changes) and in parallel forking (when you have multiple callee parties in the same time).
These advantages makes the creation of more complex Class 5 features possible and much, much easier, with only… 1 additional script function – everything else is automatically done for you. Enjoy it !