
DTMF (acronym of dual tone multi frequency) is the signal that your phone sends to your carrier when you press your phone’s touch keys during an ongoing call. The primary usage of DTMF tones is to control IVR (Interactive Voice Response) applications, by using the tones to choose certain options from a list.
From a SIP proxy perspective, detecting these tones can be useful in order to provide added services to your customers such as enabling/disabling certain features during a call, or perhaps authenticating a call. This article describes how you can create a setup that detects DTMF tones and pushes them to the OpenSIPS 3.1 script, where you can implement your own call control logic.
Use cases
When providing the service to your customers, you are also supplying them a list of code combinations that they can dial during a call. Each of this combination can translate to a different call behavior. Once you manage to intercept this DTMF tones and map them against a valid action, you can implement a certain service logic. Some examples, but not limited to, of services that you can offer are:
- choose a star code to enable or disable call recording – once the star code is detected in an ongoing call, you can trigger the siprec call pausing/resuming functions. Although these are not yet present, they will be available in the OpenSIPS 3.1 stable version
- put a call on hold, or resume a call that is on hold – Once the star code is received, you can use the dlg_send_sequential MI method to send a re-invite to the participant you want to be on hold
- trigger certain actions, such as inject an announcement in the middle of the call – this would be easily implemented using the new media_exchange module in OpenSIPS 3.1
- authenticate users by asking them for a PIN number – once 4 DTMF digits are received, one can match them against a database, and if the PIN does not match, terminate the dialog using the dlg_end_dlg command.
- transfer a party of an ongoing call to an arbitrary number dialed – when dialing a special star code followed by a phone number, you could generate a REFER method using the dlg_send_sequential command to ask a party to call that provided phone number
All these features can soon be implemented using the new OpenSIPS 3.1 LTS.
The following sections describe how to build this using OpenSIPS 3.1 and what are the other tools you need to intercept DTMF tones so that you can implement your call logic.
Implementation
In VoIP, there are three popular methods that an user agent can use to send DTMF tones to another user agent:
- SIP INFO method – this method is also called out-of-band, due to the fact that the DTMF tone is not sent through the media channel, but through the signalling channel, in a SIP INFO method
- In-band audio tones encoded in the RTP stream – DTMF codes are encoded directly into the RTP (voice) stream
- In-band tones encoded as Named Telephone Events (RFC 4733, and before it, the deprecated RFC 2833) – DTMF tones are encoded in special RTP packets, with their own designated payload type, making them easier to detect and decode
While for the out-of-band method, OpenSIPS can easily detect the sequential INFO messages and extract the DTMF tone from them, for the in-band methods things are no longer so simple. That is because OpenSIPS, as a SIP Proxy, is not involved in the RTP/media flow, therefore it does not even “see” the RTP messages containing DTMF codes. Luckily, we have other tools, such as RTPProxy and RTPEngine, that are able to insert themselves in the middle of the media flow, detect the DTMF codes and push them to OpenSIPS. Once these events are received, OpenSIPS can deliver them to the script level using the Event Interface. All you have to do is to engage these tools in the path of the media flow.
The following paragraphs present how to configure RTProxy and RTPEngine, as well as OpenSIPS, to receive DTMF events in the script.
RTPProxy
The ability of RTPProxy to detect DTMF tones has been recently added in the rtpp_2_1_dtmf branch on 26th of November 2019, and will soon be merged in the master branch. This version is able to detect RFC2833/4733 in-band events and send them to OpenSIPS to the configured notification socket. All you have to do in terms of RTPProxy configuration is to provision the -n parameter with the value of OpenSIPS’ notification socket.
In terms of OpenSIPS configuration, besides specifying the notification socket, which is the same socket OpenSIPS uses to receive RTP timeout disconnect events, you will also need to specify to all rtpproxy-* commands the d flag, indicating you are interested in DTMF events from that user agent. For example, one can use the following snippet to catch DTMF tones from the caller of a call:
if (is_method("INVITE") && !has_totag())
rtpproxy_offer("d");
Once RTPProxy detects a DTMF tone it sends it to OpenSIPS, which in turn converts it to a E_RTPPROXY_DTMF event and raises it using the Event Interface. Using this mechanism one can have its own external application that can be notified for this event, or can have an event_route in the script that treats this event:
loadmodule "event_route.so"
event_route[E_RTPPROXY_DTMF] {
if ($param(stream) == 0)
$var(direction) = "caller";
else
$var(direction) = "callee";
xlog("[DTMF] received tone=$param(digit) from $var(direction) in $param(id)\n");
}
And that’s it – you have a fully working environment where you can detect DTMF tones and push them in OpenSIPS script, where you can perform whatever logic you need to offer your customers.
RTPEngine
Starting with version mr7.4, RTPEngine provides support for detecting both RFC 2833/4733, as well as in-band encoded DTMF tones, and send them to an arbitrary destination. The latest OpenSIPS 3.1 can listen for these events and convert them to an E_RTPENGINE_NOTIFICATION event, that can be triggered in script, or to an external Event Interface application.
In order to configure DTMF detection using RTPEngine, one has to define in the RTPEngine config the using dtmf-log-dest parameter, pointing to the same value as the notification_sock. Below you can find some configuration snippets
- RTPEngine configuration
[rtpengine]
dtmf-log-dest = 127.0.0.1:9876
- OpenSIPS Configuration
# OpenSIPS configuration file
...
modparam("rtpengine", "notification_sock", "127.0.0.1:9876")
...
- OpenSIPS Event handling
loadmodule "event_route.so"
event_route[E_RTPENGINE_NOTIFICATION] {
if ($param(type) == "DTMF")
xlog("[DTMF] received tone=$param(event) from tag=$param(source_tag) in $param(callidid)\n");
}
And again, that is it! You are now receiving your calls DTMF keys in OpenSIPS script, where you can do any action you like.
Acknowledgements
Many thanks to the RTPProxy and RTPEngine maintainers, Maksym Sobolyev and Richard Fuchs for providing the DTMF detection features to their projects.
If you would like to learn more about OpenSIPS and its features, join us to the anual OpenSIPS Summit, 5th-8th May 2020, in Amsterdam, NL.
Is it possible to use such a scenario (when using RTPEngine) if I have an OpenSIPS cluster configured that uses several RTP proxies specified in the SQL database?
LikeLike
Sure, this is possible, however you will have to make sure that notifications are sent to the right OpenSIPS instance – use a Virtual IP or something to make that possible.
LikeLike