Redis and Limits with FreeSWITCH Module mod_hiredis

Quick Intro to Limits

There are two primary types of limits: concurrent limits and interval limits. A concurrent limit only looks at how many things are active at the moment. This could be the maximum number of calls up on the system or users in a conference, for example. Concurrent limits only track how many of the allowed slots are currently in use. As soon as someone leaves and frees their spot, someone is allowed to join. An interval limit cares less about how many calls are up at the moment and more about how many new calls have come in within a given period of time. This could be the maximum number of calls allowed per second, per minute, per hour, per day, etc, without taking into consideration the length of the call or the number of concurrent calls.

Using mod_hiredis

You can use mod_hiredis to implement call-per-second limits, cost per minute limits, concurrent call limits, outbound gateway limits, and more. General dialplan apps and syntax can be found on the FreeSWITCH limits page.

Note: In my previous redis post, you will see the use of 'hiredis_raw' when issuing redis commands. 'hiredis_raw' is effectively running any custom command you want against your hiredis instance. 'hiredis' apps that I've written use the redis APIs directly.

Dialplan Examples

For a working example of implementing call limits with mod_hireds, first add a limit_exceeded extension to the FreeSWITCH dialplan.

Open the FreeSWITCH dialplan. This example will use the public profile.

 cd /usr/local/freeswitch/conf/dialplan
 emacs public.xml

Assuming you have installed sounds, add the following extension with the playback action:

 <extension name="limit_exceeded">
   <condition field="destination_number" expression="^limit_exceeded$">
     <action application="playback" data="/usr/local/freeswitch/sounds/en/us/callie/8000/ivr/ivr-you_may_exit_by_hanging_up.wav"/>
     <action application="hangup"/>
   </condition>
 </extension>

Passthrough Concurrent Call Limits

Now, there a few ways to handle checking the limit. One method is to create a passthrough extension followed by the destination extension. The pre-configured public dialplan includes several pass through extensions. Add the following extensions after call_debug and before public_extensions, so that your dialplan includes:

 <extension name="limit" continue="true">
   <condition>
     <action application="limit" data="hiredis default exclusive_limit 3"/>
   </condition>
 </extension>

 <extension name="exclusive_room">
   <condition field="destination_number" expression="^(3000)$">
     <action application="transfer" data="$1 XML default"/>
   </condition>
 </extension>

For testing purposes, the exclusive_room extension sends the caller to default dialplan conference extension 3000.

Apply the dialplan changes by reloading xml in fs_cli

 reloadxml

Call into extension 3000. From Linphone, enter sip:3000@[your_ip]:5080. Once the 3 allowed calls have come in, notice that the 4th and all subsequent callers attempting to dial into the 3000 conference are played a sound file and disconnected.

Embedded Concurrent Call Limits

Another method for implementing the same functionality as the above exclusive_room example involves setting and checking the limit the exclusive_room extension. Remove the previous limit and exclusive_room extensions, and add the following:

 <extension name="exclusive_room">
   <condition field="destination_number" expression="^(3000)$">
     <action application="limit" data="hiredis default exclusive_limit 3 limit_exceeded XML public"/>
     <action application="transfer" data="$1 XML default"/>
   </condition>
 </extension>

If the limit is not yet exceeded, the caller will continue to the next action (in this case, the transfer), otherwise, the caller will be sent to the limit_exceeded extension as specified.

Reloading the xml and calling extension 3000 produces the same results as before, allowing a maximum of 3 concurrent calls and sending all subsequent attempts to the limit_exceeded extension.

Interval Limits

Where concurrent call limits use whole numbers to indicate the maximum allowed at a given time, interval limits use the fraction format: [num_allowed] / [within_num_seconds]. Yes, it is always in seconds. As an example, to allow 100 new calls per minute, use 100/60. For 100 per hour, use 100/3600.

Interval limits are highly useful in setting up barriers to fraud. If an individual's username was permitted a new call limit maximum of 10 calls per minute and they started making multiple failed calls or their account was hacked, they system would give them a buffer of up to 10 calls per minute, averaging 1 call per 6 seconds. In another case, a provider might fine you for exceeding a certain number of calls per second, and setting an internal enforcement of the interval limit could save a lot of money and headache.

Using the exclusive_room example, let's say that, no matter how many people are in the conference, you only want to allow 2 new people to join per 30 seconds. The new version of the extension would look like this:

 <extension name="exclusive_room">
   <condition field="destination_number" expression="^(3000)$">
     <action application="limit" data="hiredis default exclusive_limit 3 limit_exceeded XML public"/>
     <action application="limit" data="hiredis default exclusive_interval_limit 2/30 limit_exceeded XML public"/>
     <action application="transfer" data="$1 XML default"/>
   </condition>
 </extension>

Other Apps

Mod_hiredis supports other FreeSWITCH limit applications, including limit_execute. This action performs, in the same line, a check on the limit to make sure it is not exceeded and an action to take if within the limit. limit_execute can be used in succession to handle call distribution, as in the below:

 <action application="limit_execute" data="hiredis outbound carrier1 5 bridge sofia/gateway/carrier1/${destination_number}" />
 <action application="limit_execute" data="hiredis outbound carrier2 5 bridge sofia/gateway/carrier2/${destination_number}" />

For info on this and other FreeSWITCH limit applications, please see the FreeSWITCH limits page. Stay tuned as support for more limit APIs are added to mod_hiredis.

Category
Tagcloud
Powered by Pelican
which takes great advantage of Python