Documentation -> Tutorials -> B2BUA
Back-to-Back User Agent
written by Anca Vamanu
Table of Content (hide)
OpenSIPS has many features but in the way it behaves when a media session is established, it is not more than a proxy, meaning that it only takes the messages from one side and pass them on the other side. However, this has proven not to be enough as to provide certain services it is required for the server to be aware of the state of the sessions, monitor and control them. A Back-to-Back User Agent is exactly this, a entity in the SIP network which has the ability to control or start media sessions. The name comes from the behavior, since in fact what is required is for the B2BUA to stand in the middle and establish two dialogs with both end points that will eventually exchange media.
B2BUA in OpenSIPS is an implementation of the behavior of a B2BUA as defined in RFC 3261 that offers the possibility to build certain services on top of it. It consists of two modules:
The picture bellow shows the architecture of the B2BUA implementation.
The reason for which the architecture has two parts is to allow extensions and integration with other system that might implement their own logic interpretor. Instead of the b2b_logic module, another module with a different logic interpretor or scenario source can be placed there and use the interface that the b2b_entities module offers to build quickly a new B2BUA implementation. The b2b_entities role in the processing is an independent one that is required in any B2B implementation and it is therefore encoded in a separate module. It offer an upper level library that will make the implementation of another logic interpreter and applier much easier. The separation enhances and encourages extension and integration with other systems.
The two parts composing B2BUA in OpenSIPS are bound to each other in a control-notify relationship. The b2b_logic module controls the b2b_entities by sending commands and telling it what messages to send and the b2b_entities modules notifies the b2b_logic module when a request or a reply is received for a dialog that the B2B is handling.
The name represents in fact the type if transaction entity that is created at the beginning. So there will be a
The services are defined in documents called scenarios. A scenario instantiation is an application of a scenario that is currently in progress. The b2b_logic module might be told to initialize a scenario in two ways: from the script, by calling a function that the module exports when an initial request is received, or by sending an external command. When receiving one of this two events, the b2b_logic module will create a record(corresponding to the red small boxes in the drawing) with the information for that scenario instantiation. Also at this moment, the b2b_logic module tells the b2b_entities module to create the entities(server and/or clients) that it requires. The record mainly stores a relation to the scenario document that it must follow, the state of the scenario application and the identifiers for the entities in b2b_entities module.
As can be seen in the picture, the b2b_entities module is the bottom half part of B2BUA and it deals with the actual network message exchange. To achieve this it uses directly the functions provided by the tm module for sending requests and replies and for receiving replies. Also the tm module announce it when a reply for a request that it has sent is received. For requests inside dialog, the b2b_entities module registers a prescript function that catches this requests. In the current implementation, this requests don't go into the script because the prescript function returns '0'. As mentioned earlier, when receiving a reply or request that is matched to a known dialog, the b2b_entities module does no further action but notifies the b2b_logic module about this event. The b2b_logic module which is the upper half, will then decide what actions should be taken and sends back control commands to the b2b_entities module.
There are two ways to trigger a B2B service.
The function that can be called from the script has the name b2b_init_request and has 6 parameters:
b2b_init_request ( scenario_name, param1, param2, param3, param4, param5)
NOTE: This function has to be called on the initial Invite only ( the B2BUA must be in the middle of the call from the beginning).
The first parameter is the name of the scenario to be instantiated. So it is the job of the script writer to decide when a certain scenario should be applied . The next arguments are parameters needed by the scenario. As it shall be seen later, a scenario can require some values to be given as parameters in contrast to hard coding them, making the scenario configurable.
The MI command has the name b2b_trigger_scenario and takes exactly the same parameters as the script function.
Ex: Fifo MI command
This service can only be selected from the script, because it has sense only when a dialog is initiated. It does not require any parameter. The id for this scenario is top hiding.
Ex: Calling top hiding service
if(is_method("INVITE") && src_ip=="10.10.10.10")
The scenario documents are loaded at startup and their paths in the system must be provided through module parameters that belong to the b2b_logic module. There are two parameters, one of each type of scenario: scenario_script and scenario_extern.
Ex: Loading B2BUA scenarios
modparam("b2b_logic", "script_scenario", "/usr/local/opensips/etc/b2bua/scenario_script.xml")
The scenarios are defined as XML documents because of their adaptability and because they are easy to understand and write.
A scenario is a predefined behavior that will be interpreted by the B2B Logic. The decision when the the scenario will be applied must be taken by the server administrator in the configuration file or triggered by an extern application with an MI command.
The scenario is not rigid, but configurable through some parameters that will have to be provided to the B2B logic when requesting the instantiation of a certain scenario.
The root element has the tag 'scenario'.
<scenario id="prepaid" name="MS start and end" param="2" type="script">
It has three parameters:
A B2B scenario document has two parts:
The init section provides indications about the entities that must be created at the beginning of the scenario. The init node has as a subnode a bridging node meaning that the entities created there will eventually be connected in a media session.
There can be two types of entities:
Some parameters must be defined for the entities. Both server and client entities must be given an id that will be used to identify the entity later in the script. For the server entity no other parameters need to be defined.
For the client entities it is compulsory to define the destination where the messages will be sent. For this a destination sub node must be defined. The syntax of the destination node is:
The destination value can be provided in more ways
The client entity can also have a type subnode. The only defined value for this node is 'message'. If type node with message value is present, it means that the client will be created using the info from received SIP message: the body, the caller URI, some SIP headers(Accept, Supported, Content-Type). Defining this node does not mean that the destination will be taken from this message and still a destination node must be defined.
In addition to the bridging node, you can also define a state node. The meaning of states in the b2b scenario is that of labels in the evolution of the scenario that can be used as conditions when defining rules. A state node in the init node specifies the state that the scenario instantiation will enter after the init part will be executed.
Below there are two examples of scenario init parts, one that creates entities based on a received message and in which the dialog is initiated by the b2bua that puts two entities in contact.
The rules have two parts:
The condition part decides whether a rule should be applied for the current event. The events are represented by the receipt of a SIP request or SIP reply. The action part may define a request or reply to be sent out.
In the scenario document, the rules node has two children, requests and replies, separating the two types of events. Then both replies and requests have children with names of the possible requests inside dialog: 'invite', 'ack', 'bye' and for each more rules can be defined.
Ex: Scenario rules node structure
Rules condition part
The extra conditions that can be defined for a rule filter the scenario state and the direction of the message.
A condition will be matched if the scenario instantiation is in the same state as the state specified in the condition.
The direction of a message is specified with a sender node. The sender can be a certain entity specified with a type and an id, or a entity category, being sufficient to specify only the type.
Rules action part
In this first version there are four possible actions, with the possibility to extend them in the future. The actions are described in the table bellow.
Bellow is an action example:
No scenario document must be defined for this usage case. This is a built in mechanism and it can be requested to the B2B Logic by specifying the name "top hiding". The functionality is a simple pass through with the creation of a new dialog on the other side and transferring all the messages received on one side to the other side taking care only to change the dialog information.
Here is the theoretical expected message trace:
This scenario can be used by a company for prepaid users to announce them at the beginning of the call what their credit is and at the end of the call what their remaining credit is.
What must happen at session level is:
In B2BUA terms, this is a script scenario that can be instantiating by specifying the id prepaid. It requires 2 parameters:
To establish this sessions the SIP message flow has to look like this( it is assumed that the same media server is used):
The full scenario document is printed bellow:
The last test case is called “Marketing”, because it suits very well to the requirements of a marketing campaign through phone. The company might choose a list of potential costumers to call and announce about a new product/offer/discount. The message will be a recorded one, but the costumer will also be offered the possibility to talk to a human operator. If the costumer does not hung up the phone before the recorded message ends, it will be connected to a human operator. This is also a good means to filter the interested costumers and make the process more efficient with less resources used.
The OpenSIPS B2BUA must connect two end points, start the call from the middle. It is different from the other examples, since the call is initiated by the B2BUA and it is triggered by a MI command.
The id which must be mentioned to start this service is 'marketing'. It requires 3 parameters
Below is the theoretical message flow that should occur for this functionality to be achieved.
The scenario document that describes this service is:
The B2BUA component can also be configured to handle blind transfers(with REFER SIP message). This is useful when in the platform there are devices that do not accept the REFER method. The scenario for this case is very simple and has one rule for when a REFER is received. This rule tells the B2BUA to end the call with the user agent that sent the refer message and to bridge the peer with the user specified in the 'Refer-To' header.
The scenario document that describes this service is:
You must note that, a call that is handled by the B2B will not have the normal ‘proxy like’ interaction with the script.
Once you ask b2b to handle a call, you won't see the future in-dialog request in the normal route. The reason is that in the normal route you do proxy operations - changes on the message, routing decisions, but for the b2b calls those requests will have the b2b as an endpoint. The b2b will then generate new messages that will be sent on the other side. It will not forward the received ones. Those new generated can be accessed in local_route.
If the scenario is called from script on an initial Invite, you must take care to drop this request after calling b2b_init_request() function on it ( call 'exit', don't call t_relay() on it ).
When using b2b all the changes that you want to perform on a message must be done in local_route on the new generated request that will be sent out.
Because sometimes it is required to also access the received requests, you can define a special route b2b_request route where you can do 'read-only' operation on the request, like accounting or logging. Also, you can define a special b2b_reply route where you can see the received replies.
As a conclusion, when a call is handled by the b2bua, SIP messages for that call will be accessible in:
Also, note that dialog module does not work with B2BUA. The reason is that this module was designed to handle proxy dialogs.
There are some requirements for a configuration file that enables the B2BUA services.
Also please note that you need to configure the tm module to pass provisional replies. For this you need to set the module parameter:
modparam("tm", "pass_provisional_replies", 1)
You can find here a configuration file example that loads the two scenarios presented in this tutorial and enables the prepaid service for a certain user. Also the mi_fifo module is loaded here and it will be possible to send MI commands to instantiate the marketing scenario.
Special B2B route
The requests and replies that are received by the B2BUA server, belonging to the dialogs it is handling will not go into the script as normal request do. The reason for this is that this are not normal requests where the server is a proxy, but the server is an endpoint in the dialog and therefore they should not go through the same routes. However, it is normal for this request to be seen from the script and allow the script writer to do the processing it desires based on them. For this, it is possible to define two special B2B routes - one for requests and one for replies. The routes are of type route and have their name defined in the modules parameters script_req_route and script_reply_route.
modparam("b2b_entities", "script_req_route", "b2b_request")
Failure route not available for B2B
It is impossible to have a t_on_failure() mechanism (which is transaction specific) on a B2BUA scenario (where you have multiple dialogs, with multiple transactions) - for complex scenarios, with multiple dialogs, you cannot say for which transaction to trigger the failure route for. The "topo hiding" scenario is a very simple B2BUA scenario, but you cannot have a general "on_failure" concept for all b2bua scenarios.
A solution is to consider that b2bua is a separate instance (logically speaking) which selects types/classes of destinations. A proxy instance will responsible for routing inside the class of destinations.
For ex: in a scenario we can sent in the first place the call to Media Server for some announcement and later to PSTN GW. In a first step, the b2bua scenario will sent to proxy the call with RURI pointing to "a class" of media servers - the proxy will select the proper media server and do the failover between the media servers, totally transparent for the b2bua. In a similar way, on the second step, the b2bua scenario will indicate to proxy that it wants to have the call to be sent to PSTN GW (as type of destination) - the proxy will do lcr, drouting, failover between the GW.