
The Back-to-back user agent support in OpenSIPS has seen many enhancements and new capabilities in the last couple of release cycles, starting with OpenSIPS 3.1. From clustering/ replication in version 3.1, to dropping the XML control logic in favor of native OpenSIPS scripting in 3.2 and many others, most of these additions made the B2BUA in OpenSIPS more flexible and feature-rich.
But despite this, there were still core B2B mechanisms that had some flaws and limitations that needed to be addressed, for example, the way a SIP entity from an ongoing B2B session is re-bridged with a new participant. Since the philosophy behind the new OpenSIPS 3.4 release is consolidating the previous work and existing features, this has been the perfect time to finally rework the bridging related mechanisms and fix the past issues.
Previous Flaws With The Bridging Mechanism
As we have mentioned above, the main issue with the bridging mechanism before version 3.4, was the re-bridging of an existing participant in a B2B call with a new destination. More precisely, due to potentially long ringing time on the new entity we get a delaying of the ACK sent to the original entity and possibly call disconnection.
This happens as a consequence of how the SDP negotiation works on the old leg and how the new call leg is started. When the b2b_bridge() script function is called (or a bridging action is triggered by another module via the internal API), the OpenSIPS B2BUA first sends an INVITE without body to the original entity and then uses the SDP received in the 200 OK to create the new INVITE for the new destination. At this point, the ACK (with body) to be sent to the existing entity is delayed until the new entity provides its SDP answer to be presented on the other side.

As such, a relatively long ringing time causes problems from two perspectives:
- in terms of SIP, the original entity will probably attempt retransmissions of the 200 OK and even terminate the session if the ACK doesn’t arrive within an expected timeout;
- in terms of actual media flow, the bridged entity is now disconnected from any peer.
Workaround
A workaround for this issue already exists, but involves having an extra participant in the re-bridging process, a media server that can answer quickly and provide some provisional media while the new destination answers.
New Bridging Sequence
The provisional media mechanism will still be available but OpenSIPS 3.4 also provides two straightforward approaches to prevent the re-bridging problems discussed previously. The objective for both solutions is to eliminate the ringing time interval between the 200 OK and ACK on any of the call legs. The basic idea behind this is to have the new entity already answer the call before triggering a SDP renegotiation on the old entity. So if we do have to include at some point, SDP from the other side in an ACK , the 200 OK would always be an answer to a reINVITE (in order to receive it quickly).
Late SDP negotiation with the new entity
The new default bridging sequence when calling the b2b_bridge() function (or a bridging action is triggered via the internal API) is the following:
- optionally, put the old entity on hold first, to avoid media gaps;
- use late SDP negotiation to contact the new destination;
- when the new entity answers, send a reINVITE to trigger a SDP renegotiation with the old entity.

Additional SDP renewal step
In summary, the basic steps of the alternative bridging mechanism are:
- optionally put the old entity on hold first;
- call the new destination using normal SDP negotiation;
- after the new entity answers, send a reINVITE without body to the old entity to trigger a SDP renegotiation.
For cases where the new SIP entity to be bridged may not support late SDP at all, OpenSIPS 3.4 provides an alternative mechanism. First, the new destination is contacted using the SDP received from the old entity in the initial bridging step that started the current B2B session. After the call on the new leg is established, a reINVITE without body is sent to the old entity, in order to trigger a SDP renegotiation. This way, the original entity has a chance to offer the latest SDP that it wishes to use. From this point on, the behavior is basically similar to previous OpenSIPS versions. The important difference here though is that the new entity has already answered and we’re now only sending a reINVITE which should normally be quickly replied.
Same as with the late SDP approach discussed in the previous section, an initial step of putting the old entity on hold may be included in this re-bridging sequence.

Handling Bridging Failover
Another aspect of building complex and flexible B2B scenarios may well be handling in some way the cases where the initial call fails to establish, or even the re-bridging of a new destination is not successful. Before OpenSIPS 3.4, the whole B2B session would fail and there was no way to retry a different destination.
Doing failover for a bridging action is now possible via the new b2b_bridge_retry() function, that can be used in the dedicated b2b_logic module’s routes when handling a negative reply. This works for both the initial bridging step that starts the B2B session or any re-bridging during the B2B scenario.
The OpenSIPS script snippet below showcases the use of this function in a basic b2b_logic reply route:
route[b2b_logic_reply] {
if ($b2b_logic.entity(id) == "callee" && $rm == "INVITE" && $rs >= 300) {
b2b_client_new("media_fail", "sip:media2@opensips.org");
b2b_bridge_retry("media_fail");
} else {
b2b_handle_reply();
}
}
Conclusions
The new 3.4 release continues to improve the B2BUA capabilities offered by OpenSIPS, but this time taking a look at long known issues with the bridging mechanism and coming up with the proper solutions.
You can learn more about all the B2B related work in OpenSIPS 3.4 during the OpenSIPS Summit 2023. Join us and learn all the news of this 3.4 major release.