<!-- Module User's Guide -->

<chapter>
	
	<title>&adminguide;</title>
	
	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
	The B2BUA implementation in OpenSIPS is separated in two layers:
	<itemizedlist>
		<listitem><para>
		a lower one (implemented in the b2b_entities module) - the basic functions
		of a UAS and UAC
		</para></listitem>
		<listitem><para>
		an upper one (implemented in b2b_logic module) - which represents the logic
		engine of B2BUA, responsible of actually implementing the B2BUA services
		using the functions offered by the low level.
		</para></listitem>
	</itemizedlist>
	</para>
	<para>
	This module is a B2BUA upper level implementation that can be used along with the
	b2b_entities module in order to provide various B2BUA services (eg. PBX features).
	The actual logic of the B2BUA scenarios can be implemented in dedicated script routes.
	</para>
	<para>
	A B2B session can be triggered in two ways:
	<itemizedlist>
		<listitem>
			from the script - at the receipt of an initial INVITE message
		</listitem>
		<listitem>
			with an extern command (MI) command - the server will connect two
			end points in a session(Third Party Call Control).
		</listitem>
	</itemizedlist>
	</para>
	<para>
	High Availability for B2B sessions can be achieved by enabling the clustering support
	offered by the the lower <emphasis>b2b_entities</emphasis> module (by setting the
	<ulink url="https://opensips.org/docs/modules/3.1.x/b2b_entities.html#param_cluster_id">
	cluster_id</ulink> modparam from <emphasis>b2b_entities</emphasis>).
	</para>
	</section>

	<section id="scenario_logic" xreflabel="Scenario Logic">
	<title>Scenario Logic</title>
	<para>
		After initializing a B2B session, the call legs will be handled by the b2b_logic
		module and the first step will be to put the two initial entities in contact.
		Requests and replies belonging to these dialogs will not enter the script through
		the standard OpenSIPS routes but instead will be handled in b2b_logic dedicated routes
		(defined through the <xref linkend="param_script_req_route"/> and
		<xref linkend="param_script_reply_route"/> modparams or, the custom routes given as
		parameters to <xref linkend="func_b2b_init_request"/>).
		The further steps of the scenario can be implemented in these routes, by calling
		dedicated b2b_logic script functions in order to perform various actions. Normal
		"proxy-like" OpenSIPS functions should not be executed in the b2b_logic routes.
	</para>
	<para>
		Some messages will be handled automatically by the module and will not enter the
		b2b_logic routes at all (BYE requests received while in the process of bridging two
		entities, ACKs/BYEs/replies for disconnected entities). Also, if no dedicated b2b_logic
		reply route is defined, replies will be handled internally by the module, with the
		same effects as calling <xref linkend="func_b2b_handle_reply"/> from such a route if it were defined.
	</para>
	</section>

	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; Modules</title>
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>b2b_entities, a db module</emphasis>
			</para>
			</listitem>
			</itemizedlist>
	</section>
	
	<section>
		<title>External Libraries or Applications</title>
		<para>
		No libraries or applications required before running &osips; with this module.
		</para>
	</section>
	</section>

	<section id="exported_parameters" xreflabel="Exported Parameters">
		<title>Exported Parameters</title>
	<section id="param_hash_size" xreflabel="hash_size">
		<title><varname>hash_size</varname> (int)</title>
		<para>
			The size of the hash table that stores the session entities.
		</para>
		<para>
		<emphasis>Default value is <quote>9</quote>
		</emphasis>
		 (512 records).
		</para>
		<example>
		<title>Set <varname>server_hsize</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "hash_size", 10)
...
	</programlisting>
		</example>
	</section>

	<section id="param_script_req_route" xreflabel="script_req_route">
		<title><varname>script_req_route</varname> (str)</title>
		<para>
			The name of the script route to be called when requests belonging to
			an ongoing B2B session are received.
		</para>
		<example>
		<title>Set <varname>script_req_route</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "script_req_route", "b2b_request")
...
	</programlisting>
		</example>
	</section>

	<section id="param_script_reply_route" xreflabel="script_reply_route">
		<title><varname>script_reply_route</varname> (str)</title>
		<para>
			The name of the script route to be called when replies belonging to
			an ongoing B2B session are received.
		</para>
		<example>
		<title>Set <varname>script_repl_route</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "script_reply_route", "b2b_reply")
...
	</programlisting>
		</example>
	</section>

	<section id="param_cleanup_period" xreflabel="cleanup_period">
		<title><varname>cleanup_period</varname> (int)</title>
		<para>
			The time interval at which to search for an hanged b2b context.
			A session is considered expired if the duration of a session exceeds its
			defined lifetime. At that moment, BYE is sent in all the dialogs from that
			context and the context is deleted.
		</para>
		<para>
		<emphasis>Default value is <quote>100</quote>.</emphasis>
		</para>
		<example>
		<title>Set <varname>cleanup_period</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "cleanup_period", 60)
...
	</programlisting>
		</example>
	</section>

	<section id="param_custom_headers_regexp" xreflabel="custom_headers_regexp">
		<title><varname>custom_headers_regexp</varname> (str)</title>
		<para>
		Regexp to search SIP header by names that should be passed
		from the dialog of one side to the other side. There are a number
		of headers that are passed by default. They are: 
		<itemizedlist>
			<listitem>Max-Forwards (it is decreased by 1)</listitem>
			<listitem>Content-Type</listitem>
			<listitem>Supported</listitem>
			<listitem>Allow</listitem>
			<listitem>Proxy-Require</listitem>
			<listitem>Session-Expires</listitem>
			<listitem>Min-SE</listitem>
			<listitem>Require</listitem>
			<listitem>RSeq</listitem>
		</itemizedlist>
		If you wish some other headers to be passed also you should define them
		by setting this parameter.
		</para>
		<para>
		It can be in forms like "regexp", "/regexp/" and "/regexp/flags".
		</para>
		<para>Meaning of the flags is as follows:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>i</emphasis> - Case insensitive search.
			</para></listitem>
			<listitem><para>
			<emphasis>e</emphasis> - Use extended regexp.
			</para></listitem>
		</itemizedlist>
		<para>
		<emphasis>Default value is <quote>NULL</quote>.</emphasis>
		</para>
		<example>
		<title>Set <varname></varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "custom_headers_regexp", "/^x-/i")
...
	</programlisting>
		</example>
	</section>

	<section id="param_custom_headers" xreflabel="custom_headers">
		<title><varname>custom_headers</varname> (str)</title>
		<para>
		A list of SIP header names delimited by ';' that should be passed
		from the dialog of one side to the other side. There are a number
		of headers that are passed by default. They are: 
		<itemizedlist>
			<listitem>Max-Forwards (it is decreased by 1)</listitem>
			<listitem>Content-Type</listitem>
			<listitem>Supported</listitem>
			<listitem>Allow</listitem>
			<listitem>Proxy-Require</listitem>
			<listitem>Session-Expires</listitem>
			<listitem>Min-SE</listitem>
			<listitem>Require</listitem>
			<listitem>RSeq</listitem>
		</itemizedlist>
		If you wish some other headers to be passed also you should define them
		by setting this parameter.
		</para>
		<para>
		<emphasis>Default value is <quote>NULL</quote>.</emphasis>
		</para>
		<example>
		<title>Set <varname></varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "custom_headers", "User-Agent;Date")
...
	</programlisting>
		</example>
	</section>
	<section id="param_db_url" xreflabel="db_url">
		<title><varname>db_url</varname> (str)</title>
		<para>
			Database URL.
		</para>
		<example>
		<title>Set <varname>db_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "db_url", "mysql://opensips:opensipsrw@127.0.0.1/opensips")
...
	</programlisting>
		</example>
	</section>
		<section id="param_cachedb_url" xreflabel="cachedb_url">
			<title><varname>cachedb_url</varname> (str)</title>
			<para>
				URL of a NoSQL database to be used. Only Redis is supported
				at the moment.
			</para>
			<example>
			<title>Set <varname>cachedb_url</varname> parameter</title>
			<programlisting format="linespecific">
...
modparam("b2b_logic", "cachedb_url", "redis://localhost:6379/")
...
		</programlisting>
			</example>
		</section>
		<section id="param_cachedb_key_prefix" xreflabel="cachedb_key_prefix">
			<title><varname>cachedb_key_prefix</varname> (string)</title>
			<para>
			Prefix to use for every key set in the NoSQL database.
			</para>
			<para>
			<emphasis>
				Default value is <quote>b2bl$</quote>.
			</emphasis>
			</para>
			<example>
			<title>Set <varname>cachedb_key_prefix</varname> parameter</title>
			<programlisting format="linespecific">
...
modparam("b2b_logic", "cachedb_key_prefix", "b2b")
...
	</programlisting>
			</example>
		</section>
	<section id="param_update_period" xreflabel="update_period">
		<title><varname>update_period</varname> (int)</title>
		<para>
			The time interval at which to update the info in database.
		</para>
		<para>
		<emphasis>Default value is <quote>100</quote>.</emphasis>
		</para>
		<example>
		<title>Set <varname>update_period</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "update_period", 60)
...
	</programlisting>
		</example>
	</section>
	<section id="param_max_duration" xreflabel="max_duration">
		<title><varname>max_duration</varname> (int)</title>
		<para>
			The maximum duration of a call.
		</para>
		<para>
		<emphasis>Default value is <quote>12 * 3600 (12 hours)</quote>.</emphasis>
		</para>
		<para>If you set it to 0, there will be no limitation.</para>
		<example>
		<title>Set <varname>max_duration</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "max_duration", 7200)
...
	</programlisting>
		</example>
	</section>

	<section id="param_contact_user" xreflabel="contact_user">
		<title><varname>contact_user</varname> (int)</title>
		<para>
			If set to 1, adds user from From: header to generated Contact:
		</para>
		<para>
		<emphasis>Default value is <quote>0</quote>.</emphasis>
		</para>
		<example>
		<title>Set <varname>contact_user</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "contact_user", 1)
...
	</programlisting>
		</example>
	</section>

	<section id="param_b2bl_from_spec_param" xreflabel="b2bl_from_spec_param">
		<title><varname>b2bl_from_spec_param</varname> (string)</title>
		<para>
			The name of the pseudo variable for storing the new
			<quote>From</quote> header.
			The PV must be set before calling <quote>b2b_init_request</quote>.
		</para>
		<para>
		<emphasis>Default value is <quote>NULL</quote> (disabled).</emphasis>
		</para>
		<example>
		<title>Set <varname>b2bl_from_spec_param</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "b2bl_from_spec_param", "$var(b2bl_from)")
...
route{
	...
	# setting the From header
	$var(b2bl_from) = "\"Call ID\" &lt;sip:user@opensips.org&gt;";
	...
	b2b_init_request("top hiding");
	...
}
	</programlisting>
		</example>
	</section>

	<section id="param_server_address" xreflabel="server_address">
		<title><varname>server_address</varname> (str)</title>
		<para>
			The IP address of the machine that will be used as Contact in
			the generated messages. This is compulsory only when OpenSIPS
			starts a call from the middle. For scenarios triggered by received
			calls, if it is not set, it is constructed dynamically from the
			socket where the initiating request was received.
			This socket will be used to send all the requests, replies for that
			session.
			This parameter support Pseudo-Variables.
		</para>
		<example>
		<title>Set <varname>server_address</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "server_address", "sip:sa@10.10.10.10:5060")
...
	</programlisting>
		</example>
		<example>
		<title>Set <varname>server_address</varname> parameter using Pseudo-Variables</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "server_address", "sip:$socket_in(advertised_ip):$socket_in(advertised_port)")
...
	</programlisting>
		</example>
	</section>

	<section id="param_init_callid_hdr" xreflabel="init_callid_hdr">
		<title><varname>init_callid_hdr</varname> (str)</title>
		<para>
			The module offers the possibility to insert the original callid in a header
			in the generated Invites. If you want this, set this parameter to the name
			of the header in which to insert the original callid.
		</para>
		<example>
		<title>Set <varname>init_callid_hdr</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "init_callid_hdr", "Init-CallID")
...
	</programlisting>
		</example>
	</section>
	<section id="param_db_mode" xreflabel="db_mode">
		<title><varname>db_mode</varname> (int)</title>
		<para>
			The B2B modules have support for the 3 type of database storage
		</para>
		<para>
		<itemizedlist>
				<listitem>NO DB STORAGE - set this parameter to 0</listitem>
				<listitem>WRITE THROUGH (synchronous write in database) - set this parameter to 1</listitem>
				<listitem>WRITE BACK (update in db from time to time) - set this parameter to 2</listitem>
		</itemizedlist>
		</para>
		<para>
		<emphasis>Default value is <quote>2</quote> (WRITE BACK).</emphasis>
		</para>
		<example>
		<title>Set <varname>db_mode</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "db_mode", 1)
...
	</programlisting>
		</example>
	</section>

	<section id="param_db_table" xreflabel="db_table">
		<title><varname>db_table</varname> (str)</title>
		<para>
			Name of the database table to be used
		</para>
		<para>
		<emphasis>Default value is <quote>b2b_logic</quote> </emphasis>
		</para>
		<example>
		<title>Set <varname>db_table</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "db_table", "some_table_name")
...
	</programlisting>
		</example>
	</section>

	<section id="param_b2bl_th_init_timeout" xreflabel="b2bl_th_init_timeout">
		<title><varname>b2bl_th_init_timeout</varname> (int)</title>
		<para>
			Call setup timeout for topology hiding scenario.
		</para>
		<para>
		<emphasis>Default value is <quote>60</quote> </emphasis>
		</para>
		<example>
		<title>Set <varname>b2bl_th_init_timeout</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "b2bl_th_init_timeout", 60)
...
	</programlisting>
		</example>
	</section>


	<section id="param_b2bl_early_update" xreflabel="b2bl_early_update">
		<title><varname>b2bl_early_update</varname> (int)</title>
		<para>
			Allow bridging of calls in early stage by issuing a "UPDATE" request
		</para>
		<para>
		<itemizedlist>
				<listitem>0 - Do not bridge dialogs in early stage</listitem>
				<listitem>1 - Try to update an session in early stage by sending an UPDATE</listitem>
		</itemizedlist>
		</para>
		<para>
		<emphasis>Default value is <quote>0</quote> Do not bridge dialogs in early stage</emphasis>
		</para>
		<example>
		<title>Set <varname>b2bl_early_update</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "b2bl_early_update", 1)
...
	</programlisting>
		</example>
	</section>	
	<section id="param_old_entity_term_delay" xreflabel="old_entity_term_delay">
		<title><varname>old_entity_term_delay</varname> (int)</title>
		<para>
			When the <emphasis>b2b_bridge_request</emphasis> is being used with the
			<emphasis>late_bye</emphasis> flag, this parameter can delay the moment
			when the BYE is being sent to the terminating entity. Thus, instead of
			terminating it when the new entity is established, the BYE is delayed
			with the value of this param, expressed in seconds.
		</para>
		<para>
		<emphasis>Default value is <quote>0</quote> - send BYE on the spot</emphasis>
		</para>
		<example>
		<title>Set <varname>old_entity_term_delay</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("b2b_logic", "old_entity_term_delay", 2) # delay the BYE with 2 seconds
...
	</programlisting>
		</example>
	</section>	

	</section>

	<section id="exported_functions" xreflabel="exported_functions">
		<title>Exported Functions</title>
	<section id="func_b2b_init_request" xreflabel="b2b_init_request()">
		<title>
		<function moreinfo="none">b2b_init_request(id, [flags], [req_route],
			[reply_route])</function>
		</title>
		<para>
			This function initializes a new B2B session based on an initial INVITE.
			A new server entity and a new client entity must be created before running
			this function, with <xref linkend="func_b2b_server_new"/> and
			<xref linkend="func_b2b_client_new"/>, respectively. These are the initial
			entities to be connected and further scenario logic can be implemented in
			the b2b_logic dedicated routes.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>scenario_id (string)</emphasis> - identifier for
				the scenario of this B2B session. The special value <emphasis>top hiding</emphasis>
				initializes an internal topology hiding scenario. This scenario will do
				a simple pass-through of messages from one side to another, and no additional
				scripting or dedicated routes are required.
			</para></listitem>
			<listitem><para>
				<emphasis>flags (string, optional)</emphasis> - CSV list of the following flags:
				<itemizedlist>
					<listitem><para>
					<emphasis>setup-timeout=[nn]</emphasis> - Call setup timeout. 0 sets
					timeout to max_duration value. Example: "setup-timeout=300".
					</para></listitem>
					<listitem><para>
					<emphasis>transparent-auth</emphasis> - Transparent authentication.
					In this mode b2b passes your 401 or 407 authentication request to
					destination server.
					</para></listitem>
					<listitem><para>
					<emphasis>preserve-to</emphasis> - Preserve To: header.
					</para></listitem>
				</itemizedlist>
			</para></listitem>
			<listitem><para>
				<emphasis>req_route (string, optional)</emphasis> - name of the script route
				to be called when requests belonging to this B2B session are received. This
				parameter will override the global <xref linkend="param_script_req_route"/>
				modparam for this particular B2B session.
			</para></listitem>
			<listitem><para>
				<emphasis>reply_route (string, optional)</emphasis> - name of the script route
				to be called when replies belonging to this B2B session are received. This
				parameter will override the global <xref linkend="param_script_reply_route"/>
				modparam for this particular B2B session.
			</para></listitem>
		</itemizedlist>
	<para>
		This function can be used from REQUEST_ROUTE.
	</para>
	<note><para>
		If you have a multi interface setup and want to change the outbound interface,
		it is mandatory to use the "force_send_socket()" core function before passing
		control to b2b function. If you do not do it, the requests may be correctly routed,
		but the SIP pacakge may be invalid (as Contact, Via, etc).
	</para></note>
		<example>
			<title><function>b2b_init_request</function> usage</title>
		<programlisting format="linespecific">
...
if(is_method("INVITE") &amp;&amp; !has_totag() &amp;&amp; prepaid_user()) {
   ...
   # create initial entities
   b2b_server_new("server1");
   b2b_client_new("client1", $var(media_uri));

   # initialize B2B session
   b2b_init_request("prepaid");
   exit;
}
...
	</programlisting>
		</example>
	</section>

	<section id="func_b2b_server_new" xreflabel="b2b_server_new()">
		<title>
		<function moreinfo="none">b2b_server_new(id, [adv_contact], [extra_hdrs],
			[extra_hdr_bodies])</function>
		</title>
		<para>
			This function creates a new server entity (dialog where OpenSIPS acts as a UAS)
			to be used for initializing a new B2B session. It should only be
			used for initial INVITES, before calling <xref linkend="func_b2b_init_request"/>.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>id (string)</emphasis> - ID used to reference this entity
				in further B2B actions.
			</para></listitem>
			<listitem><para>
				<emphasis>adv_contact (string, optional)</emphasis> - Contact header to
				advertise in generated messages.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_hdrs (var, optional)</emphasis> - AVP variable holding a list
				of extra headers (the header names) to be added for any request sent
				to this entity.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_hdr_bodies (var, optional)</emphasis> - AVP variable holding a
				list of extra header bodies (corresponding to the headers given in the
				<emphasis>extra_hdrs</emphasis> parameter) to be added for any request
				sent to this entity.
			</para></listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
			<title><function>b2b_server_new</function> usage</title>
		<programlisting format="linespecific">
...
if(is_method("INVITE") &amp;&amp; !has_totag()) {
   b2b_server_new("server1", $avp(b2b_hdrs), $avp(b2b_hdr_bodies));
   ...
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_client_new" xreflabel="b2b_client_new()">
		<title>
		<function moreinfo="none">b2b_client_new(id, dest_uri, [proxy], [from_dname],
			[adv_contact], [extra_hdrs], [extra_hdr_bodies])</function>
		</title>
		<para>
			This function creates a new client entity (dialog where OpenSIPS acts as a UAC)
			to be used for initializing a new B2B session or for a bridge action. The function
			can be used before calling <xref linkend="func_b2b_init_request"/> or
			<xref linkend="func_b2b_bridge"/>.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>id (string)</emphasis> - ID used to reference this entity
				in further B2B actions.
			</para></listitem>
			<listitem><para>
				<emphasis>dest_uri (string)</emphasis> - URI of the new destination.
			</para></listitem>
			<listitem><para>
				<emphasis>proxy (string, optional)</emphasis> - URI of the outbound proxy
				to send the INVITE to.
			</para></listitem>
			<listitem><para>
				<emphasis>from_dname (string, optional)</emphasis> - Display name to
				use in the From header.
			</para></listitem>
			<listitem><para>
				<emphasis>adv_contact (string, optional)</emphasis> - Contact header to
				advertise in generated messages.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_hdrs (var, optional)</emphasis> - AVP variable holding a list
				of extra headers (the header names) to be added for any request sent
				to this entity.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_hdr_bodies (var, optional)</emphasis> - AVP variable holding a
				list of extra header bodies (corresponding to the headers given in the
				<emphasis>extra_hdrs</emphasis> parameter) to be added for any request
				sent to this entity.
			</para></listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE and the b2b_logic request routes.
		</para>
		<example>
			<title><function>b2b_client_new</function> usage</title>
		<programlisting format="linespecific">
...
b2b_client_new("client1", "sip:alice@opensips.org");
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_bridge" xreflabel="b2b_bridge()">
		<title>
		<function moreinfo="none">b2b_bridge(entity1, entity2, [provmedia_uri], [flags])</function>
		</title>
		<para>
			This function bridges two entities, in the context of an existing B2B session
			(the initial entities are already connected). At least one of the two entities
			has to be a new client entity.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>entity1 (string)</emphasis> - ID of the first entity to bridge;
				the special values: <emphasis>peer</emphasis> and <emphasis>this</emphasis>
				can also be used to refer to existing entities.
			</para></listitem>
			<listitem><para>
				<emphasis>entity2 (string)</emphasis> - ID of the second entity to bridge;
				the special values: <emphasis>peer</emphasis> and <emphasis>this</emphasis>
				can also be used to refer to existing entities.
			</para></listitem>
			<listitem><para>
				<emphasis>provmedia_uri (string, optional)</emphasis> - URI of the provisional
				media server to be connected with the caller while the callee answers.
			</para></listitem>
			<listitem><para>
				<emphasis>flags (string, optional)</emphasis> - CSV list of the following flags:
				<itemizedlist>
					<listitem><para>
					<emphasis>max_duration=[nn]</emphasis> - Maximum duration of the B2B
					session. If the lifetime expires, the B2BUA will send BYE messages to both
					ends and delete the record. Example: "max_duration=300".
					</para></listitem>
					<listitem><para>
					<emphasis>notify</emphasis> - Enable rfc3515 NOTIFY to inform the agent
					sending the REFER of the status of the reference.
					</para></listitem>
					<listitem><para>
					<emphasis>rollback-failed</emphasis> - Rollback call to state before
					bridging in case of transfer failed, don't hangup the call
					(default behaviour).
					</para></listitem>
					<listitem><para>
					<emphasis>hold</emphasis> - Put the old entity on hold before bridging
					it to the new entity.
					</para></listitem>
					<listitem><para>
					<emphasis>no-late-sdp</emphasis> - Do not attempt late SDP negociation
					with the new entity. Start the bridging by first contacting the new entity
					using the initial SDP received from the old entity. After the new entity
					answers, send a reINVITE without body to the old entity. Use the current
					SDP received in this new answer from the old entity to trigger a
					renegociation with the new entity.
					</para></listitem>
				</itemizedlist>
			</para></listitem>
		</itemizedlist>
		<para>
		This function can be used from the b2b_logic request routes.
		</para>
		<example>
			<title><function>b2b_bridge</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_request] {
   ...
   b2b_client_new("client2", $hdr(Refer-To));

   b2b_bridge("peer", "client2");
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_bridge_retry" xreflabel="b2b_bridge_retry()">
		<title>
		<function moreinfo="none">b2b_bridge_retry(new_entity)</function>
		</title>
		<para>
			This function can be used to retry a failed bridging action by contacting
			a new destination. A new client entity must be created before running this
			function with <xref linkend="func_b2b_client_new"/>.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>entity1 (string)</emphasis> - ID of the new entity to bridge.
			</para></listitem>
		</itemizedlist>
		<para>
		This function can be used from the b2b_logic reply route.
		</para>
		<example>
			<title><function>b2b_bridge</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_reply] {
   ...
   if ($b2b_logic.entity(id) == "client1" &amp;&amp; $rm == "INVITE" &amp;&amp; $rs >= 300) {
      b2b_client_new("client_retry", "sip:alice@opensips.org");

      b2b_bridge_retry("client_retry");
   } else {
      b2b_handle_reply();
   }
   ...
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_pass_request" xreflabel="b2b_pass_request()">
		<title>
		<function moreinfo="none">b2b_pass_request()</function>
		</title>
		<para>
			This function passes a request belonging to an existing B2B session
			to the peer entity. The function should be called for all requests unless
			a different action is required to implement the scenario logic (eg. a
			bridge action).
		</para>
		<para>
		This function can be used from the b2b_logic request routes.
		</para>
		<example>
			<title><function>b2b_pass_request</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_request] {
   if ($rm != "BYE") {
      b2b_pass_request();
      exit;
   } else {
      # delete the current entity and bridge the peer to a new one
   }
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_handle_reply" xreflabel="b2b_handle_reply()">
		<title>
		<function moreinfo="none">b2b_handle_reply()</function>
		</title>
		<para>
			This function processes the received reply by taking the appropriate actions
			for the current state of the ongoing B2B session (pass reply to peer,
			send INVITE or ACK to comeplete an ongoing bridge action etc.).
			The function should be called for all replies, if a b2b_logic reply
			route is defined.
		</para>
		<para>
		This function can be used from the b2b_logic reply routes.
		</para>
		<example>
			<title><function>b2b_handle_reply</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_reply] {
    xlog("B2B REPLY: [$rs $rm] from entity: $b2b_logic.entity(id)\n");
    b2b_handle_reply();
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_send_reply" xreflabel="b2b_send_reply()">
		<title>
		<function moreinfo="none">b2b_send_reply(code, reason[, headers[, body]])</function>
		</title>
		<para>
			This function sends a reply to the entity that sent the current
			request.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>code (int)</emphasis> - reply code
			</para></listitem>
			<listitem><para>
				<emphasis>reason (string)</emphasis> - reply reason string
			</para></listitem>
			<listitem><para>
				<emphasis>headers (string, optional)</emphasis> - additional headers
			</para></listitem>
			<listitem><para>
				<emphasis>body (string, optional)</emphasis> - message body
			</para></listitem>
		</itemizedlist>
		<para>
		This function can be used from the b2b_logic request routes.
		</para>
		<example>
			<title><function>b2b_send_reply</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_request] {
   if ($rm == "REFER") {
      b2b_send_reply(202, "Accepted");
      ...
   }
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_delete_entity" xreflabel="b2b_delete_entity()">
		<title>
		<function moreinfo="none">b2b_delete_entity()</function>
		</title>
		<para>
			This function deletes the entity that sent the current request.
		</para>
		<para>
		This function can be used from the b2b_logic request routes.
		</para>
		<example>
			<title><function>b2b_delete_entity</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_request] {
   if ($rm == "BYE") {
      b2b_send_reply(200, "OK");
      b2b_delete_entity();
      ...
   }
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_end_dlg_leg" xreflabel="b2b_end_dlg_leg()">
		<title>
		<function moreinfo="none">b2b_end_dlg_leg()</function>
		</title>
		<para>
			This function sends a BYE request to the entity that sent
			the current request. It is not required to also call
			<xref linkend="func_b2b_delete_entity"/> in order to delete
			the current entity.
		</para>
		<para>
		This function can be used from the b2b_logic request or reply routes.
		</para>
		<example>
			<title><function>b2b_end_dlg_leg</function> usage</title>
		<programlisting format="linespecific">
...
route[b2b_logic_request] {
   if ($rm == "REFER") {
      b2b_send_reply(202, "Accepted");
      b2b_end_dlg_leg();
   }
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_bridge_request" xreflabel="b2b_bridge_request()">
		<title>
		<function moreinfo="none">b2b_bridge_request(b2bl_key,entity_no, [adv_contact], [flags])</function>
		</title>
		<para>
			This function will bridge an initial INVITE with one of the
			particapnts from an existing b2b session.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>b2bl_key (string)</emphasis> - a string that
				contains the b2b_logic key. The key can also be in the form
				of <emphasis>callid;from-tag;to-tag</emphasis>.
			</para></listitem>
			<listitem><para>
				<emphasis>entity_no (int)</emphasis> - an integer that
				holds the entity of the entity/participant to bridge.
			</para></listitem>
			<listitem><para>
				<emphasis>adv_contact (string, optional)</emphasis> - Contact header to
				advertise in generated messages.
			</para></listitem>
			<listitem><para>
				<emphasis>flags (string, optional)</emphasis> - Flags that can modify the
				behavior of the function. Available flags are:
				<itemizedlist>
				<listitem><para>
					<emphasis>late_bye</emphasis> - instead of terminating the replaced entity
					on the stop, leave it pending until the new enity fully establishes.
				</para></listitem>
				</itemizedlist>
			</para></listitem>
		</itemizedlist>
		<example>
			<title><function>b2b_bridge_request</function> usage</title>
		<programlisting format="linespecific">
...
if ($rU == "pickup") {
    # get the b2b logic key of the parked call for this user
    cache_fetch("local", "$fU", $var(b2bl_key));
    cache_remove("local", "$fU");

    if ($var(b2bl_key) != NULL)
        b2b_bridge_request($var(b2bl_key), 0);
    else
        send_reply(481, "Call/Transaction Does Not Exist");

    exit;
}
...
		</programlisting>
		</example>
	</section>

	<section id="func_b2b_trigger_scenario" xreflabel="b2b_trigger_scenario()">
		<title>
		<function moreinfo="none">b2b_trigger_scenario(scenario, [params], peer1,
			[extra_headers_peer1], [extra_headers_contents_peer1],
			peer2
			[extra_headers_peer2], [extra_headers_contents_peer2])</function>
		</title>
		<para>
			This function triggers a certain scenario from routing script, e.g.
			out-of-dialog REFERs.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>scenario (string)</emphasis> - Name of the scenario to be triggered.
			</para></listitem>
			<listitem>
				<para>
					<emphasis>params (string, optional)</emphasis> - Parameters to be used in this scenario (optionally as CSV)
				</para>
				<itemizedlist>
					<listitem><para>
						<emphasis>n</emphasis> - Enable rfc3515 NOTIFY to inform the agent sending the
						REFER of the status of the reference.
					</para></listitem>
					<listitem><para>
						<emphasis>session key (string, optional)</emphasis> - Internal session key, if the NOTIFY should be sent
						in a different session on this B2B-UA (e.g. useful for receiving out-of-dialog REFERs)
					</para></listitem>
					<listitem><para>
						<emphasis>party of remote session (int, optional)</emphasis> - If the NOTIFY should be sent to a different session, which
						side should receive the NOTIFY of the session (0 = A-Party of the session, 1 = B-Party of the session)
					</para></listitem>
				</itemizedlist>
			</listitem>
			<listitem>
				<para>
					<emphasis>peer1 (string)</emphasis> - Parameters to define the A-Party of the triggered scenario
				</para>
				<itemizedlist>
					<listitem><para>
						<emphasis>entitiy_name (string)</emphasis> - Name of the entity
					</para></listitem>
					<listitem><para>
						<emphasis>RURI (string)</emphasis> - R-URI of the entity to contact
					</para></listitem>
					<listitem><para>
						<emphasis>Proxy (string, optional)</emphasis> - Outbound Proxy to be used for this entity
					</para></listitem>
					<listitem><para>
						<emphasis>Display-Name (string, optional)</emphasis> - Display Name to be used for this entity
					</para></listitem>
				</itemizedlist>
			</listitem>
			<listitem><para>
				<emphasis>extra_headers_peer1 (var, optional)</emphasis> - AVP variable holding a list
				of extra headers (the header names) to be added for any request sent for the first entity.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_headers_contents_peer1 (var, optional)</emphasis> - AVP variable holding a
				list of extra header bodies (corresponding to the headers given in the
				<emphasis>extra_headers_peer1</emphasis> parameter) to be added for any request
				sent for the first entity.
			</para></listitem>
			<listitem><para>
				<emphasis>peer2 (string)</emphasis> - Parameters to define the B-Party of the
				triggered scenario. The format is identitical to the definition of <emphasis>peer1</emphasis>.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_headers_peer2 (var, optional)</emphasis> - AVP variable holding a list
				of extra headers (the header names) to be added for any request sent for the second entity.
			</para></listitem>
			<listitem><para>
				<emphasis>extra_headers_contents_peer2 (var, optional)</emphasis> - AVP variable holding a
				list of extra header bodies (corresponding to the headers given in the
				<emphasis>extra_headers_peer2</emphasis> parameter) to be added for any request
				sent for the second entity.
			</para></listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
			<title><function>b2b_trigger_scenario</function> usage</title>
		<programlisting format="linespecific">
...
if(is_method("REFER") &amp;&amp; !has_totag()) {
   $avp(header) = "Replaces";
   $avp(header_content) = "call-id=xyz";
   b2b_trigger_scenario("refer", "n", "conf,sip:conference@10.0.0.1", $avp(header), $avp(header_content), "callee,sip:user@10.0.0.1,sip:10.0.0.1");
   ...
}
...
		</programlisting>
		</example>
	</section>

</section>

<section id="exported_mi_functions" xreflabel="Exported MI Functions">
	<title>Exported MI Functions</title>
	<section id="mi_b2b_trigger_scenario" xreflabel="b2b_trigger_scenario">
		<title>
		<function moreinfo="none">b2b_trigger_scenario</function>
		</title>
		<para>
		This command initializes a new B2B session where OpenSIPS will start
		a call from the middle. The initial entities to be connected are
		specified through the command's parameters and further scenario logic
		can be implemented in the b2b_logic dedicated routes.
		</para>
		<para>
		Name: <emphasis>b2b_trigger_scenario</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem>
				<para><emphasis>senario_id</emphasis> : ID for the scenario of this B2B session.
				</para>
			</listitem>
			<listitem>
				<para><emphasis>entity1</emphasis> - first entity to be connected; specified
				in the following format: <emphasis>id,dest_uri[,from_dname]</emphasis> where:</para>
				<itemizedlist>
				<listitem><para>
					<emphasis>id</emphasis> - ID used to reference this entity
					in further B2B actions
				</para></listitem>
				<listitem><para>
					<emphasis>dest_uri</emphasis> - URI of the new destination
				</para></listitem>
				<listitem><para>
					<emphasis>from_dname (optional)</emphasis> - Display name to
					use in the From header.
				</para></listitem>
				</itemizedlist>
			</listitem>
			<listitem>
				<para><emphasis>entity2</emphasis> - second entity to be connected;
				specified in the same format as <emphasis>entity1</emphasis></para>
			</listitem>
			<listitem>
				<para><emphasis>context (array, optional)</emphasis> - array of B2B
				context values, in the format: <emphasis>key=value</emphasis></para>
			</listitem>
		</itemizedlist>
		<para>
		MI FIFO Command Format:
		</para>
	<programlisting  format="linespecific">
	opensips-cli -x mi b2b_trigger_scenario marketing client1,sip:bob@opensips.org client2,sip:322@opensips.org:5070 agent_uri=sip:alice@opensips.org
		</programlisting>
	</section>

	<section id="mi_b2b_bridge" xreflabel="b2b_bridge">
		<title>
		<function moreinfo="none">b2b_bridge</function>
		</title>
		<para>
			This command can be used by an external application to tell B2BUA to bridge a
			call party from an on going dialog to another destination. By default the caller
			is bridged to the new uri and BYE is set to the callee. You can instead bridge
			the callee if you send 1 as the third parameter.
		</para>
		<para>
		Name: <emphasis>b2b_bridge</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem>
				<para><emphasis>dialog_id</emphasis> : the <emphasis>b2b_logic key</emphasis>, or the
				<emphasis>callid;from-tag;to-tag</emphasis> of the ongoing dialog.
				</para>
			</listitem>
			<listitem>
				<para><emphasis>new_uri</emphasis> - the uri of the new destination</para>
			</listitem>
			<listitem>
				<para><emphasis>flag</emphasis> (optional) - used to specify that the callee must be bridged to the new destination. If not present the caller will be bridged. Possible values are
				'0' or '1'.</para>
			</listitem>
			<listitem>
				<para><emphasis>prov_media_uri</emphasis> (optional) - the uri of a media server able to play 
					provisional media starting from the beginning of the bridging scenario
					to the end of it. It is optional. If not present, no other entity will be
					envolved in the bridging scenario</para>
			</listitem>
		</itemizedlist>
		<para>MI FIFO Command Format:</para>
	<programlisting  format="linespecific">
	opensips-cli -x mi b2b_bridge 1020.30 sip:alice@opensips.org
	</programlisting>
		<para>opensips-cli Command Format:</para>
	<programlisting  format="linespecific">
	opensips-cli -x mi b2b_bridge 1020.30 sip:alice@opensips.org
	</programlisting>
	</section>

	<section id="mi_b2b_list" xreflabel="b2b_list">
		<title>
		<function moreinfo="none">b2b_list</function>
		</title>
		<para>
			This command can be used to list the internals of b2b_logic entities.
		</para>
		<para>
		Name: <emphasis>b2b_list</emphasis>
		</para>
		<para>Parameters: <emphasis>none</emphasis></para>
		<itemizedlist>
		</itemizedlist>
		<para>MI FIFO Command Format:</para>
	<programlisting  format="linespecific">
	opensips-cli -x mi b2b_list
	</programlisting>
	</section>

	<section id="mi_b2b_terminate_call" xreflabel="b2b_terminate_call">
		<title>
		<function moreinfo="none">b2b_terminate_call</function>
		</title>
		<para>
			Terminates an ongoing B2B session.
		</para>
		<para>
		Name: <emphasis>b2b_terminate_call</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem>
				<para><emphasis>key</emphasis> : the <emphasis>b2b_logic key</emphasis>
				or the <emphasis>callid;from-tag;to-tag</emphasis> of
				one of call legs of the ongoing session.
				</para>
			</listitem>
		</itemizedlist>
		<para>MI FIFO Command Format:</para>
	<programlisting  format="linespecific">
	opensips-cli -x mi b2b_terminate_call 159.0
	</programlisting>
	</section>

</section>

<section id="exported_pseudo_variables">
	<title>Exported Pseudo-Variables</title>

	<section id="b2b_logic.key" xreflabel="$b2b_logic.key">
	<title>
		<varname>$b2b_logic.key</varname>
	</title>
	<para>
		This is a read-only variable that returns the b2b_logic key of the
		ongoing B2B session.
	</para>
	<para>
		The variable can be used in request route, local_route and the dedicated
		routes defined through the <emphasis>b2b_entities</emphasis> and
		<emphasis>b2b_logic</emphasis> modules.
	</para>
	<example>
	<title><varname>$b2b_logic.key</varname> usage</title>
	<programlisting format="linespecific">
...
local_route {
   ...
   if ($b2b_logic.key) {
      xlog("request belongs to B2B session: $b2b_logic.key\n");
      ...
   }
   ...
}
...
	</programlisting>
	</example>
	</section>

	<section id="b2b_logic.entity" xreflabel="$b2b_logic.entity">
	<title>
		<varname>$b2b_logic.entity(field)[idx]</varname>
	</title>
	<para>
		This is a read-only variable that returns information about the
		entities(dialogs) involved in the ongoing B2B session.
	</para>
	<para>
		The available entity information is:
		<itemizedlist>
			<listitem><para>
				the Call-ID of the dialog, accessible by using the
				<emphasis>callid</emphasis> subname;
			</para></listitem>
			<listitem><para>
				the entity key, accessible by using the
				<emphasis>key</emphasis> subname or no subname at all.
			</para></listitem>
			<listitem><para>
				the entity ID, accessible by using the
				<emphasis>id</emphasis> subname.
			</para></listitem>
			<listitem><para>
				the From-Tag of the dialog, accessible by using the
				<emphasis>fromtag</emphasis> subname.
			</para></listitem>
			<listitem><para>
				the To-Tag of the dialog, accessible by using the
				<emphasis>totag</emphasis> subname.
			</para></listitem>
		</itemizedlist>
	</para>
	<para>
		The index is used to select which entity from the B2B session to refer
		to. The only possible values are <emphasis>0</emphasis> or <emphasis>1
		</emphasis> and correspond to the positions of the entities
		in the scenario. Initially, this depends on the order in which the entities
		are created. In the case of the internal topology hiding scenario,
		<emphasis>0</emphasis> is the caller and <emphasis>1</emphasis> is the callee.
		When a further bridge action happens, the bridged entity is always placed on the
		<emphasis>0</emphasis> index and the new entity on <emphasis>1</emphasis>.
	</para>
	<para>
		If no index is provided, the variable will refer to the entity(dialog)
		which the current SIP message belongs to.
	</para>
	<para>
		The variable can be used in request route, local_route and the dedicated
		routes defined through the <emphasis>b2b_entities</emphasis> and
		<emphasis>b2b_logic</emphasis> modules.
	</para>
	<example>
	<title><varname>$b2b_logic.entity</varname> usage</title>
	<programlisting format="linespecific">
...
modparam("b2b_entities", "script_request_route", "b2b_request")
...
route[b2b_request] {
   ...
   xlog("received request for entity: $b2b_logic.entity\n");
   ...
   if ($rm == "BYE" &amp;&amp; $b2b_logic.entity == $(b2b_logic.entity[1]))
      xlog("Disconnecting callee\n")
   ...
}
...
	</programlisting>
	</example>
	</section>

	<section id="b2b_logic.ctx" xreflabel="$b2b_logic.ctx">
	<title>
		<varname>$b2b_logic.ctx(key)</varname>
	</title>
	<para>
		This is a read-write variable that provides access to a custom
		Key-Value storage(of string values) in the context of the ongoing
		B2B session.
	</para>
	<para>
		The variable can be used in request route, local_route and the dedicated
		routes defined through the <emphasis>b2b_entities</emphasis> and
		<emphasis>b2b_logic</emphasis> modules. In the main request route
		the variable can be used for storing a new context value even before
		instantiating the scenario with <emphasis>b2b_init_request()</emphasis>.
	</para>
	<para>
		Setting the variable to <emphasis>NULL</emphasis> will delete the value
		at the given key.
	</para>
	<example>
	<title><varname>$b2b_logic.ctx</varname> usage</title>
	<programlisting format="linespecific">
...
modparam("b2b_entities", "script_reply_route", "b2b_reply")
...
route {
   ...
   b2b_init_request("prepaid", "sip:alice@127.0.0.1");

   $b2b_logic.ctx(my_extra_info) = "my_value";
   ...
}
...
route[b2b_reply] {
   ...
   xlog("my info: $b2b_logic.ctx(my_extra_info)\n");
   ...
}
...
	</programlisting>
	</example>
	</section>

	<section id="b2b_logic.scenario" xreflabel="$b2b_logic.scenario">
	<title>
		<varname>$b2b_logic.scenario(key)</varname>
	</title>
	<para>
		This is a read-only variable that returns the scenario ID of the ongoing
		B2B session
	</para>
	<para>
		The variable can be used in request route, local_route and the dedicated
		routes defined through the <emphasis>b2b_entities</emphasis> and
		<emphasis>b2b_logic</emphasis> modules.
	</para>
	<example>
	<title><varname>$b2b_logic.scenario</varname> usage</title>
	<programlisting format="linespecific">
...
route[b2b_logic_request] {
   if ($b2b_logic.scenario == "prepaid") {
      route(prepaid);
   } else {
      route(marketing);
   }
}
...
	</programlisting>
	</example>
	</section>

</section>

</chapter>

