RTP Relay Module
     __________________________________________________________

   Table of Contents

   1. Admin Guide

        1.1. Overview
        1.2. Multiple Branches
        1.3. RTP Relay Engines
        1.4. Dependencies

              1.4.1. OpenSIPS Modules
              1.4.2. External Libraries or Applications

        1.5. Exported Parameters

              1.5.1. route_offer (string)
              1.5.2. route_answer (string)
              1.5.3. route_delete (string)
              1.5.4. route_copy_offer (string)
              1.5.5. route_copy_answer (string)
              1.5.6. route_copy_delete (string)

        1.6. Exported Functions

              1.6.1. rtp_relay_engage(engine, [set])

        1.7. Exported MI Functions

              1.7.1. rtp_relay_list
              1.7.2. rtp_relay_update
              1.7.3. rtp_relay_update_callid

        1.8. Exported Pseudo-Variables

              1.8.1. $rtp_relay
              1.8.2. $rtp_relay_peer
              1.8.3. $rtp_relay_ctx()

   2. Contributors

        2.1. By Commit Statistics
        2.2. By Commit Activity

   3. Documentation

        3.1. Contributors

   List of Tables

   2.1. Top contributors by DevScore^(1), authored commits^(2) and
          lines added/removed^(3)

   2.2. Most recently active contributors^(1) to this module

   List of Examples

   1.1. Set route_offer parameter
   1.2. route_offer route usage
   1.3. Set route_answer parameter
   1.4. route_answer route usage
   1.5. Set route_delete parameter
   1.6. rtp_relay_delete route usage
   1.7. Set rtp_relay_copy_offer parameter
   1.8. Set rtp_relay_copy_offer usage
   1.9. Set rtp_relay_copy_answer parameter
   1.10. Set rtp_relay_copy_answer usage
   1.11. Set rtp_relay_copy_delete parameter
   1.12. Set rtp_relay_copy_delete usage
   1.13. rtp_relay_engage usage
   1.14. rtp_relay_list usage
   1.15. rtp_relay_update usage
   1.16. rtp_relay_update_callid usage

Chapter 1. Admin Guide

1.1. Overview

   The purpose of this module is to simplify the usage of
   different RTP Relays Servers (such as RTPProxy, RTPEngine,
   Media Proxy) in OpenSIPS scripting, as well as to provide
   various complex features that rely on the usage of RTP relays
   (such as media re-anchoring).

   The module provides the logic to engage a specific RTP relay in
   a call during initial INVITE, and then it will handle the
   entire communication with the RTP relay, until the call
   terminates.

   Moreover, one can specify various flags that modify the way RTP
   engines use each user agent's SDP - these flags are persistent
   throughout the entire RTP session, and are being used for
   further in-dialog requests. These flags can be specified
   through the $rtp_relay and/or $rtp_relay_peer variables at
   initial INVITE, and are then passed along with the RTP relay
   context until the end of the call. They can also be modified
   during sequential in-dialog requests.

   This is not a stand-alone module that communicates directly
   with RTP relays, but rather a generic interface that is able to
   interact with the modules that interact with each specific RTP
   Relay (such as rtpproxy or rtpengine) and implement their
   specific communication protocol.

1.2. Multiple Branches

   The module is able to handle RTP relay for multiple branches,
   with different flags flavors. Each branch can have its flags
   tuned through the $rtp_relay variable - if the variable is
   provisioned in the main route, then the flags are inherited by
   all further branches, unless specifically modified per branch.
   To modify a specific branch, one needs to specify the desired
   branch index as variable index (i.e. $(rtp_relay[1]) = "cor").
   When provisioned in a branch route, the flags are only changed
   for that specific branch.

   Starting with OpenSIPS 3.3, branches can be identified based on
   their participant's to_tag. This features becomes handy when
   using rtp_relay in B2B mode, where peers can no longer be
   identified simply by an index. However, this feature works in
   dialog secenatios as well.

   The multiple branches behavior is handled differently by the
   back-end engine, depending on its capabilities. For example,
   rtpengine is able to natively support calls with multiple
   branches, whereas for rtpproxy, each branch is emulated in a
   different session with a different call-id.

   When the call gets answered and a single branch remains active,
   all the other branches are destroyed and only the established
   branches remain active throughout the call.

1.3. RTP Relay Engines

   The module does not perform any SDP mangling itself, it is just
   an enabler of the different backends supported, such as
   RTPProxy or RTPEngine. These backends are called RTP Relay
   angines and they need to be specified when RTP Relay is being
   engaged.

   Starting with OpenSIPS 3.6, the module has been enhanced with
   an internal RTP Engine, which can be used to perform
   manual/custom SDP mangling by running a set of routes when an
   RTP event (such as offer, answer, delete) happens. This can be
   enabled by engaging RTP Relay with the route engine. If the
   defined routes are not being defined, then the SDP does not
   change. For more information, please check the route_offer,
   route_answer and route_delete parameters.

1.4. Dependencies

1.4.1. OpenSIPS Modules

   The following modules must be loaded before this module:
     * Dialog module - used to keep track of in-dialog requests.
     * RTP Relay module(s) - such rtpproxy, or rtpengine, or any
       module that implements the rtp_relay interface.

1.4.2. External Libraries or Applications

   The following libraries or applications must be installed
   before running OpenSIPS with this module loaded:
     * None.

1.5. Exported Parameters

1.5.1. route_offer (string)

   Route that is being run when an SDP offer happens (i.e. an
   INVITE with SDP is being processed).

   When the route is executed, the following parameters are being
   populated:
     * callid - the callid of the call being processed.
     * from_tag - the from_tag of the call being processed.
     * to_tag - the to_tag, if exists, of the call being
       processed.
     * branch - the branch that RTP relay is being engaed on - if
       engaged in the main branch, -1 is used.
     * body - optional, if an explicit body is being used,
       otherwise the message's body should be considered.
     * set - the rtp relay set being used for the call.
     * node - optional, an node Engine idenfifier - this is a user
       populated value returned after running a route_offer route
       (see the return values section below).
     * ip - optional, the IP being specified in the $rtp_relay
       variable for the current peer.
     * type - optional, the RTP type being specified in the
       $rtp_relay variable for the current peer.
     * in-iface - optional, the inbound interface that should be
       used for this peer.
     * out-iface - optional, the outbound interface that should be
       used for this peer.
     * ctx-flags - optional, global flags that are being specified
       in the $rtp_relay_ctx variable.
     * flags - optional, flags specified for this peer.
     * peer - optional, peer flags specified for the corresponding
       peer;

   When running the route, the following values are expected to be
   returned:
     * body - the newly created body to be offered. If not
       returned, the body is left unchanged.
     * node - optional, a node to be identified for further
       routes/commands executed.

   Default value is “rtp_relay_offer”.

   Example 1.1. Set route_offer parameter
...
modparam("rtp_relay", "route_offer", "custom_rtp_offer")
...

   Example 1.2. route_offer route usage
...
route[rtp_relay_offer] {
        # manually engaging RTPEngine, get the SDP, and replace it in th
e message
        return (1, $var(body));
}
...

1.5.2. route_answer (string)

   Route that is being run when an SDP answer happens (i.e. a 183
   or 200 OK reply with SDP is being processed).

   When the route is executed, the following parameters are being
   populated:
     * callid - the callid of the call being processed.
     * from_tag - the from_tag of the call being processed.
     * to_tag - the to_tag, if exists, of the call being
       processed.
     * branch - the branch that RTP relay is being engaed on - if
       engaged in the main branch, -1 is used.
     * body - optional, if an explicit body is being used,
       otherwise the message's body should be considered.
     * set - the rtp relay set being used for the call.
     * node - optional, an node Engine idenfifier - this is a user
       populated value returned after running a route_offer route.
     * ip - optional, the IP being specified in the $rtp_relay
       variable for the current peer.
     * type - optional, the RTP type being specified in the
       $rtp_relay variable for the current peer.
     * in-iface - optional, the inbound interface that should be
       used for this peer.
     * out-iface - optional, the outbound interface that should be
       used for this peer.
     * ctx->flags - optional, global flags that are being
       specified in the $rtp_relay_ctx variable.
     * flags - optional, flags specified for this peer.
     * peer - optional, peer flags specified for the corresponding
       peer;

   When running the route, the following values are expected to be
   returned:
     * body - the newly created body to be answered. If not
       returned, the body is left unchanged.

   Default value is “rtp_relay_answer”.

   Example 1.3. Set route_answer parameter
...
modparam("rtp_relay", "route_answer", "custom_rtp_answer")
...

   Example 1.4. route_answer route usage
...
route[rtp_relay_answer] {
        # again, manually engaging RTPEngine
        rtpengine_answer(,, $var(body), $rb);
        return (1, $var(body));
}
...

1.5.3. route_delete (string)

   Route that is being run when media should be disconnected (i.e.
   a CANCEL or BYE is received).

   When the route is executed, the following parameters are being
   populated:
     * callid - the callid of the call being processed.
     * from_tag - the from_tag of the call being processed.
     * to_tag - the to_tag, if exists, of the call being
       processed.
     * branch - the branch that RTP relay is being engaed on - if
       engaged in the main branch, -1 is used.
     * body - optional, if an explicit body is being used,
       otherwise the message's body should be considered.
     * set - the rtp relay set being used for the call.
     * node - optional, an node Engine idenfifier - this is a user
       populated value returned after running a route_offer route
       (see the return values section below).
     * ctx->flags - optional, global flags that are being
       specified in the $rtp_relay_ctx variable.
     * delete - optional, delete flags specified in the
       $rtp_relay_ctx variable.

   Return values are not needed.

   Default value is “rtp_relay_delete”.

   Example 1.5. Set route_delete parameter
...
modparam("rtp_relay", "route_delete", "custom_rtp_delete")
...

   Example 1.6. rtp_relay_delete route usage
...
route[rtp_relay_delete] {
        # manually removing RTPEngine session
        rtpengine_delete();
}
...

1.5.4. route_copy_offer (string)

   Route that is being executed when a new call's SDP is being
   copied.

   When the route is executed, the following parameters are being
   populated:
     * callid - the callid of the call being processed.
     * from_tag - the from_tag of the call being processed.
     * to_tag - the to_tag, if exists, of the call being
       processed.
     * branch - the branch that RTP relay is being engaed on - if
       engaged in the main branch, -1 is used.
     * set - the rtp relay set being used for the call.
     * node - optional, an node Engine idenfifier - this is a user
       populated value returned after running a route_offer route
       (see the return values section below).
     * flags - optional, flags that are being specified by the
       module which is copying the SDP.
     * copy-ctx - optional, an copy context identifier - this is a
       user populated value returned after running a
       route_copy_offer route (see the return values section
       below).

   When running the route, the following values are expected to be
   returned:
     * copy-ctx - optional, a copy context identifier that can be
       later used to identify the current copy session.

   Default value is “rtp_relay_copy_offer”.

   Example 1.7. Set rtp_relay_copy_offer parameter
...
modparam("rtp_relay", "route_copy_offer", "custom_rtp_copy_offer")
...

   Example 1.8. Set rtp_relay_copy_offer usage
...
route[rtp_relay_copy_offer] {
        # instruct a media engine to fork media and assign an identifier
        # that shall be stored in the $var(handle) variable
        return (1, $var(handle));
}
...

1.5.5. route_copy_answer (string)

   Route that is being run when an SDP for the copied stream is
   received. (i.e. a CANCEL or BYE is received).

   When the route is executed, the following parameters are being
   populated:
     * callid - the callid of the call being processed.
     * from_tag - the from_tag of the call being processed.
     * to_tag - the to_tag, if exists, of the call being
       processed.
     * branch - the branch that RTP relay is being engaed on - if
       engaged in the main branch, -1 is used.
     * body - optional, if an explicit body is being used,
       otherwise the message's body should be considered.
     * set - the rtp relay set being used for the call.
     * node - optional, an node Engine idenfifier - this is a user
       populated value returned after running a route_offer route
       (see the return values section below).
     * flags - optional, flags that are being specified by the
       module which is copying the SDP.
     * copy-ctx - optional, an copy context identifier - this is a
       user populated value returned at the end of
       route_copy_offer execution.

   Default value is “rtp_relay_copy_answer”.

   Example 1.9. Set rtp_relay_copy_answer parameter
...
modparam("rtp_relay", "route_copy_answer", "custom_rtp_copy_answer")
...

   Example 1.10. Set rtp_relay_copy_answer usage
...
route[rtp_relay_copy_answer] {
        # feed the received $param(body) to the media engine that is for
king the call
        # copy instance is identified by the $param(copy-ctx) variable
}
...

1.5.6. route_copy_delete (string)

   Route that is being run when media fork should be removed.

   When the route is executed, the following parameters are being
   populated:
     * callid - the callid of the call being processed.
     * from_tag - the from_tag of the call being processed.
     * to_tag - the to_tag, if exists, of the call being
       processed.
     * branch - the branch that RTP relay is being engaed on - if
       engaged in the main branch, -1 is used.
     * body - optional, if an explicit body is being used,
       otherwise the message's body should be considered.
     * set - the rtp relay set being used for the call.
     * node - optional, an node Engine idenfifier - this is a user
       populated value returned after running a route_offer route
       (see the return values section below).
     * flags - optional, flags that are being specified by the
       module which is copying the SDP.
     * copy-ctx - optional, an copy context identifier - this is a
       user populated value returned at the end of
       route_copy_offer execution.

   Return values are not needed.

   Default value is “rtp_relay_copy_delete”.

   Example 1.11. Set rtp_relay_copy_delete parameter
...
modparam("rtp_relay", "route_copy_delete", "custom_rtp_copy_delete")
...

   Example 1.12. Set rtp_relay_copy_delete usage
...
route[rtp_relay_copy_delete] {
        # remove the copy instance is identified by the $param(copy-ctx)
 variable
}
...

1.6. Exported Functions

1.6.1.  rtp_relay_engage(engine, [set])

   Engages the RTP Relay engine for the current initial INVITE.
   After calling this function, the entire RTP relay communication
   will be handled by the module itself, without having to
   intervene for any further in-dialog requests/replies (unless
   you specifically want to).

   The function is not performing the media requests on the spot,
   but rather registers the hooks to automatically handle any
   further media requests.

   The RTP session modifiers used are the ones provisioned through
   the $rtp_relay and/or $rtp_relay_peer variables.

   The function can be called from the main request route - in
   this case the RTP relay will be engaged for any further
   branches created, or from the branch route - in this case the
   RTP relay will only be engaged for the branch where it was
   called, or that has an associated rtp_relay provisioned.

   Meaning of the parameters is as follows:
     * engine(string) - the RTP relay engine to be used for the
       call (i.e. rtpproxy, rtpengine or route)
     * set(int, optional) - the set used for this call.

   This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
   BRANCH_ROUTE.

   Example 1.13. rtp_relay_engage usage
...
if (is_method("INVITE") && !has_totag()) {
        xlog("SCRIPT: engaging RTPProxy relay for all branches\n");
        $rtp_relay = "co";
        $rtp_relay_peer = "co";
        rtp_relay_engage("rtpproxy");
}
...

1.7. Exported MI Functions

1.7.1. rtp_relay_list

   Lists all the RTP Relay sessions engaged.

   Parameters:
     * engine - (optional) the RTP relay engine (i.e. rtpproxy or
       rtpengine).
     * set - (optional) the RTP relay set. When used, the engine
       parameter must also be specified.
     * node - (optional) the RTP relay node. When used, the engine
       parameter must also be specified.

   Example 1.14.  rtp_relay_list usage
...
## list all sessions
$ opensips-cli -x mi rtp_relay_list

## list all sessions going through a specific RTP node
$ opensips-cli -x mi rtp_relay_list rtpproxy udp:127.0.0.1:2222
...

1.7.2. rtp_relay_update

   Updates/Re-engages the RTP relays in all ongoing RTP relay
   sessions.

   This function can be used to trigger dialog in-dialog updates
   for certain ongoing RTP sessions. For all matched sessions, it
   re-engages an RTP Relay offer/answer session, then sends
   re-INVITEs to call's participants to with the updated SDP.

   Note:Running the command without a filter (such as engine or
   set) will cause all RTP relay sessions to be re-engaged.

   Note:When enforcing a new node, it is not guaranteed to be used
   - if the node is not avaialble, but a different one is, the
   active one will be chosen.

   Note:If the node is being changed, the module tries to unforce
   the previous RTP relay session, even though it might not work.

   Parameters:
     * engine - (optional) the RTP relay engine (i.e. rtpproxy or
       rtpengine) to be used as filter.
     * set - (optional) the RTP relay set to be used as filter. If
       missing, the same set will be used as it was initially
       engaged for.
     * node - (optional) the RTP relay node to be used as filter.
     * new_set - (optional) a new RTP Relay set to be used for the
       call.
     * new_node - (optional) a new RTP node to be used for the
       call. If new_set is missing, the same set will be used.

   Example 1.15.  rtp_relay_update usage
...
## update all sessions that are using rtpproxy
$ opensips-cli -x mi rtp_relay_update rtpproxy
...

1.7.3. rtp_relay_update_callid

   Updates/Re-engages the RTP relays in all ongoing RTP relay
   sessions.

   The function basically works in the same manner as
   rtp_relay_update, but is to be used to update a specific
   callid. In addition, one can also update the engine and flags
   used for the particular session.

   Parameters:
     * callid - the callid used to match the dialog to be updated.
     * engine - (optional) the new RTP relay engine (i.e. rtpproxy
       or rtpengine) to be used. If missing, the same initial
       engine is used.
     * set - (optional) the new RTP relay set to be used. If
       missing, the default same set will be used as it was
       initially engaged for.
     * node - (optional) the RTP relay node to be used. If not
       specified, the first available node is used.
     * flags - (optional) a JSON contining the caller and/or
       callee nodes, which contain new flags that should be used
       for the session. Only explicitely specified flags will be
       overwritten.

   Example 1.16.  rtp_relay_update_callid usage
...
## update a call with a working RTPproxy node
$ opensips-cli -x mi rtp_relay_update_callid 1-3758963@127.0.0.1 rtpprox
y

## update a call to use RTPEngine with a SRTP SDP for caller
$ opensips-cli -x mi rtp_relay_update_callid callid=1-3758963@127.0.0.1
\
        flags='{ "caller":{"type":"SRTP", "flags":"replace-origin"},
                "callee":{"type":"RTP", "flags"="replace-origin"}}'
...

1.8. Exported Pseudo-Variables

1.8.1. $rtp_relay

   Is used to provision the RTP back-end flags for the current
   peer - if used in the initial INVITE REQUEST route, it
   provisions the flags of the caller, whereas if used in the
   initial INVITE BRANCH/REPLY route, it provisions the callee's
   flags.

   For a sequential request, the variable represents the flags
   used for the UAC that generated the request. When used in a
   reply, the other UAC's flags are provisioned.

   In an initial INVITE scope, the variable can be provisioned per
   branch, by using the variable's index.

   For each UAC/peer, there are several flags that can be
   configured:
     * flags (default, when variable is used without a name) - are
       the flags associated with the current UAC - they are passed
       along with the offer command
     * peer - these flags are passed along in the offer command,
       but they are flags associated with the other UAC/peer
     * ip - the IP that should be advertised in the resulted SDP.
     * type - the RTP type used by the current UAC (currently only
       used by rtpengine)
     * iface - the interface used for the traffic coming from this
       UAC.
     * body - the body to be used for the UAC.
     * delete - flags to be used when the media session is
       terminated/deleted.
     * disabled - provisioned as an integer, it is used to disable
       RTP relay for this UAC.

1.8.2. $rtp_relay_peer

   This variable has the same meaning and parameters as the
   $rtp_relay variable, except that it is used to provision the
   other UAC's flags, except the current one. All other fields are
   similar.

1.8.3. $rtp_relay_ctx()

   This variable can be used to provide information about the RTP
   context, information that is not associated with any of the
   involved peers.

   The following settings can be used:
     * callid - The callid to be used for all communication with
       the rtp server. If not specified, it is taken from the
       message/dialog.
     * from_tag - The from-tag to be used for all communication
       with the rtp server. If not specified, it is taken from the
       message/dialog.
     * to_tag - The to-tag to be used for all communication with
       the rtp server. If not specified, it is taken from the
       message/dialog.
     * flags - Generic flags to be sent to all offer/answer
       requests.
     * delete - flags sent when the relay session is terminated.

Chapter 2. Contributors

2.1. By Commit Statistics

   Table 2.1. Top contributors by DevScore^(1), authored
   commits^(2) and lines added/removed^(3)
                   Name               DevScore Commits Lines ++ Lines --
   1. Razvan Crainea (@razvancrainea)   180      101     6946     1182
   2. Maksym Sobolyev (@sobomax)         6        4       10       11
   3. Norman Brandinger (@NormB)         4        2       2        2
   4. Vlad Patrascu (@rvlad-patrascu)    3        1       11       7
   5. Liviu Chircu (@liviuchircu)        3        1       1        1
   6. Vlad Paiu (@vladpaiu)              2        1       5        0

   (1) DevScore = author_commits + author_lines_added /
   (project_lines_added / project_commits) + author_lines_deleted
   / (project_lines_deleted / project_commits)

   (2) including any documentation-related commits, excluding
   merge commits. Regarding imported patches/code, we do our best
   to count the work on behalf of the proper owner, as per the
   "fix_authors" and "mod_renames" arrays in
   opensips/doc/build-contrib.sh. If you identify any
   patches/commits which do not get properly attributed to you,
   please submit a pull request which extends "fix_authors" and/or
   "mod_renames".

   (3) ignoring whitespace edits, renamed files and auto-generated
   files

2.2. By Commit Activity

   Table 2.2. Most recently active contributors^(1) to this module
                   Name                 Commit Activity
   1. Razvan Crainea (@razvancrainea) Apr 2021 - Jun 2025
   2. Liviu Chircu (@liviuchircu)     Jun 2024 - Jun 2024
   3. Norman Brandinger (@NormB)      Mar 2024 - Jun 2024
   4. Maksym Sobolyev (@sobomax)      Feb 2023 - Nov 2023
   5. Vlad Patrascu (@rvlad-patrascu) Mar 2023 - Mar 2023
   6. Vlad Paiu (@vladpaiu)           Oct 2022 - Oct 2022

   (1) including any documentation-related commits, excluding
   merge commits

Chapter 3. Documentation

3.1. Contributors

   Last edited by: Razvan Crainea (@razvancrainea).

   Documentation Copyrights:

   Copyright © 2021 OpenSIPS Solutions
