CALLING OPERATIONS module
Admin Guide
Section titled “Admin Guide”Overview
Section titled “Overview”This module provides a set of functions that allow the user to control ongoing calls. It can be used to trigger a call (either blind or attended) transfer, or put a call on hold from the proxy side, rather than the end-device side. The module binds on top of the OpenSIPS Dialog module to get information about the ongoing calls, as well as storing information about new calls that will be started.
The module also triggers a set of events over Event Interface, providing to external applications details about how calls are being transferred, and how they link between them. These events can be used to track down all the legs involved in a call transfer.
One of the biggest challenge when doing Call Transfer scenarios is linking new calls to the old calls being transferred, especially in blind call transfer scenarios. In order to solve this challenge, the module can be configured to refer old legs in two different modes, changeable using the mode parameter:
- Automatically (default mode), by adding a special parameter to the destination URI that is being sent in the REFER. When the new call comes back, the parameter will be present in the Request URI of the new call. The module will find it, link the new call to the old call, and remove the parameter from the URI.
- Manually, by using custom/external logic (such as a database, or local storage), to match the old call. In this mode, the user has to explicitly call the call blind replace function to link the two calls together.
The module can also be used to catch Notify refer events and reply to them from the OpenSIPS level. However, note that in auto mode even if the NOTIFY is handled when the dialog is matched, the request will still continue its execution of the script, unlike when manual mode is used with the call transfer notify function. In order to avoid sending the NOTIFY to the end-point, you have to drop it, like below:
...if (has_totag() && loose_route() && is_method("NOTIFY") && $hdr(Event) == "refer") drop;...Dependencies
Section titled “Dependencies”OpenSIPS Modules
Section titled “OpenSIPS Modules”The following modules must be loaded before this module:
- TM - Transaction module.
- Dialog - Dialog module for keeping track of the proxied calls.
External Libraries or Applications
Section titled “External Libraries or Applications”The following libraries or applications must be installed before running OpenSIPS with this module loaded:
- None.
Exported Parameters
Section titled “Exported Parameters”mode (string)
Section titled “mode (string)”This parameter can be used to change the mode that the module uses to match a transferred leg. Supported values are:
- param - when doing a blind transfer, the destination sent in the refer message will contain a parameter used to identify the dialog that is being replaced. this parameter will be automatically removed when the new call is received.
- manual - the user will create its own logic to match the new calls, and will call the call blind replace function to make OpenSIPS aware of the pair. Note that this mode does not handle automatically the Notify refer either, so you also have to use the call transfer notify function to handle them.
- callid - similar to the param value, except that instead of storing in the Request URI the dialog id of the call to be transfered, the actual callid is used as identifier.
Default value is “auto mode using parameters”.
...modparam("callops", "mode", "manual") # use your own logic...match_param (string)
Section titled “match_param (string)”The parameter used to match the different calls together. This is mainly using in the param mode, but it is also used internally to store different values inside the transferred dialog - make sure it does not overlap with existing dialog values.
Default value is “osid”.
...modparam("callops", "match_param", "call")...Exported Functions
Section titled “Exported Functions”call_blind_replace(callid[, leg])
Section titled “call_blind_replace(callid[, leg])”When manual mode is used, this function is called to create a mapping between the transferring call and the transferred call. It should be called when OpenSIPS receives a new call that is transferring an existing call.
Parameters:
- callid (string) - the existing call that is being transferred.
- leg (string, optional) - the leg that is being transferred. If not specified, and OpenSIPS cannot determine the leg based on its destination, the unknown tag should be used.
This function can be used only from a request route.
...if (!has_totag() && is_method("INVITE")) { if (cache_fetch("local", "callid_$si", $avp(callid))) { call_blind_replace($avp(callid)); }}...call_transfer_notify()
Section titled “call_transfer_notify()”When manual mode is used, this function should be called on in-dialog NOTIFY requests for an Event: refer header, to handle them accordingly.
Note that if the function successfully handles the NOTIFY request, the script no longer continues its execution.
This function can be used from a request route, failure route and local route.
...if (has_totag() && is_method("NOTIFY") && loose_route()) { call_transfer_notify();}...call_transfer(leg, destination) or
Section titled “call_transfer(leg, destination) or”This function triggers a blind call transfer by sending a REFER message during an ongoing call. The function needs to be run inside the context of the dialog you are transferring.
Parameters:
- leg (string) - the leg that is being transferred. Must be one of the caller or callee values.
- destination (string) - SIP URI of the destination where the leg is being transferred.
This function can be used from any route that has a dialog context.
...if (has_totag() && && loose_route()) { call_transfer("caller", "sip:announcement@127.0.0.1");}...call_transfer(leg, transfer_callid, transfer_leg[, destination]) or
Section titled “call_transfer(leg, transfer_callid, transfer_leg[, destination]) or”This function triggers an attended call transfer by sending a REFER message during an ongoing call. The function needs to be run inside the context of the dialog you are transferring.
Parameters:
- leg (string) - the leg that is being transferred. Must be one of the caller or callee values.
- transfer_callid (string) - the callid of the second dialog that is being transferred.
- transfer_leg (string) - the leg within the second call that will be transferred to leg. Must be one of the caller or callee values.
- destination (string, optional) - SIP URI of the destination where the leg is being transferred. If missing, the From/To URI of the initial call are used.
This function can be used from any route that has a dialog context.
...if (has_totag() && && loose_route()) { call_transfer("caller", "ba55b1b3-459d-4e84-a6f8-14c40e4f6ace", "callee");}...Exported MI Functions
Section titled “Exported MI Functions”call_transfer
Section titled “call_transfer”MI command to transfer an ongoing call to a new destination.
Depending on the parameters used, this command can do both blind and attended transfers scenarios. When the transfer_callid is used, then an attended transfer is performed, other wise a blind transfer is issued.
Name: call_transfer
Parameters
- callid (string) - the callid of the dialog that is being transferred.
- leg (string) - indicates the leg of the callid call that is being transferred/kept in the new transferring call. Possible values are “caller”, “callee” or “both”.
- destination (string, optional) - the URI where the call is being transferred. This parameter is mandatory for blind transfers, and optional for attended transfers. In the case of an attended transfer, if it is missing, the destination of the call is taken from the URIs in the transfer dialog.
- transfer_callid (string, optional) - mandatory in case of an attended transfer, to specify the call of the Bleg in the new call.
- transfer_leg (string, optional) - in case of an attended transfer, it specifies the participant of the transfer_callid call that will be bridged with the leg of the callid. If missing, transfer_fromtag and transfer_totag must be used to identify the tag.
- transfer_fromtag and transfer_totag (string, optional) - these parameters should always be specified together, and are used in call attended transfer scenarios where the dialog of the Bleg that is being transferred is not managed by OpenSIPS. Note that for these scenarios only the A-leg dialog will receive events about the call transfer.
MI FIFO Command Format:
# blind transfer to sip:agent@127.0.0.1opensips-cli -x mi call_transfer \ callid=4b664b48-5639-40bf-bff8-3a866c145c3b \ leg=caller \ destination=sip:agent@217.0.0.1# attended transfer between two callsopensips-cli -x mi call_transfer \ callid=e8d024db-78e5-4d18-9794-5b8ba837bed4 leg=caller \ transfer_callid=559abf97-9834-4380-bba1-a036eb245450 \ transfer_leg=caleecall_hold
Section titled “call_hold”MI command to put an ongoing call on hold.
Command returns OK if any of the legs of the call have been put on hold. If the call is already on hold, an error is returned.
Name: call_hold
Parameters
- callid (string) - the callid of the dialog that is being put on hold.
MI FIFO Command Format:
# put a call on holdopensips-cli -x mi call_hold \ callid=921b00e4-fec0-4a36-9397-a40ab74e1893call_unhold
Section titled “call_unhold”MI command to resume a call from an onhold state put by the mi call hold call.
Command returns OK if any of the legs are resumed, or an error if no leg had been previously put on hold.
Name: call_unhold
Parameters
- callid (string) - the callid of the dialog that is being resumed.
MI FIFO Command Format:
opensips-cli -x mi call_unhold \ callid=921b00e4-fec0-4a36-9397-a40ab74e1893Exported Events
Section titled “Exported Events”E_CALL_TRANSFER
Section titled “E_CALL_TRANSFER”This event is triggered during a call transfer scenario.
For a specific call transfer, multiple events are triggered, starting when the transfer is initiated, until the transfer is completed. The state parameter indicates the state of the call transfer.
For a blind transfer scenario, only one set of events are triggered, whereas for attended transfer, you will get a set of events for both dialogs involved in the transfer, as long as both are proxied through OpenSIPS
Parameters:
- callid - the callid of the call that is being transferred.
- leg - the leg (caller or callee) of the call that is being transferred.
- transfer_callid - the callid of the new call that is transferring the old callid call.
- destination - the URI destination where the leg is being transferred.
- state - the state of the transfer:
- start - triggered when the REFER message is being sent out to the transferred participant.
- notify - triggered when a NOTIFY refer event is received from the transferred participant. The status parameter contains extra information about the status of the transferring call.
- ok - triggered when the transfer is completed - the call is answered by the transferred participant.
- fail - triggered when a transfer has failed due to various reasons. If we were unable to start the call transfer (i.e. send the REFER), the status parameter is empty, otherwise it contains information about the failure.
- status - contains extra information about the success or failure of the call.
E_CALL_HOLD
Section titled “E_CALL_HOLD”Triggered during the process of putting a call on hold, or resuming a call from an on hold state.
This event is triggered twice per each leg of the call - first when the leg starts to be put on hold, and then when the leg accepts or rejects the state.
Parameters:
- callid - the callid of the call that is being put on hold, or resumed.
- leg - the leg (caller or callee) affected by the call on hold, or resumed.
- action - hold or unhold action that is being performed.
- state - the state of the action that
is being performed.
- start - triggered when the re-INVITE is being sent out to the participant being put on hold.
- ok - triggered when the on hold/resume action is successfully completed.
- fail - triggered when the action failed.
Contributors
Section titled “Contributors”By Commit Statistics
Section titled “By Commit Statistics”Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)
| # | Name | DevScore | Commits | Lines++ | Lines— |
|---|---|---|---|---|---|
| 1. | Razvan Crainea (@razvancrainea) | 48 | 24 | 2303 | 197 |
| 2. | Stefan Darius (@dariusstefan) | 14 | 5 | 656 | 158 |
| 3. | Bogdan-Andrei Iancu (@bogdan-iancu) | 3 | 1 | 2 | 1 |
| 4. | Liviu Chircu (@liviuchircu) | 3 | 1 | 1 | 1 |
(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
(3) ignoring whitespace edits, renamed files and auto-generated files
By Commit Activity
Section titled “By Commit Activity”| # | Name | Commit Activity |
|---|---|---|
| 1. | Stefan Darius (@dariusstefan) | Jun 2026 - Jul 2026 |
| 2. | Razvan Crainea (@razvancrainea) | May 2020 - Jun 2026 |
| 3. | Bogdan-Andrei Iancu (@bogdan-iancu) | Apr 2023 - Apr 2023 |
| 4. | Liviu Chircu (@liviuchircu) | Jan 2021 - Jan 2021 |
(1) including any documentation-related commits, excluding merge commits
Documentation
Section titled “Documentation”Contributors
Section titled “Contributors”Last edited by: Razvan Crainea (@razvancrainea).
License
Section titled “License”All documentation files (i.e. .md extension) are licensed under the Creative Common License 4.0