Thursday, June 6, 2013

Asterisk Dialplan and Redis Integration

I came across this very strange task that I need to have the asterisk get/set data from Redis. My initial thought was this is easy, just going to plug in a perl AGI, use redis connector and everything will be super cool. BUT the condition was I've to stay within the extensions.conf. Yes, I did try convince everyone around but to no avail. NO AGIs, use anything else however I want.

So what I did was create a small shell script which behaves as an API for Redis, and use the Asterisk System() application to GET/SET my desired memcached values.

root@asterisk1:~# vim /etc/asterisk/redis.pl

Insert the following lines in there, add more commands to it see this link: http://search.cpan.org/dist/Redis/lib/Redis.pm

#!/usr/bin/perl

my $redis_db = $ARGV[0];
my $command = $ARGV[1];
my $keyname = $ARGV[2];
my $value = $ARGV[3];

# PERL MODULE
require Redis;
my $redis = Redis->new(server => '127.0.0.1:6379');

if($redis_db > 0 && $redis_db < 16){
        $redis->select("$redis_db");
} else {
        print "using Default Redis DB\n";
}
if($command eq "GET"){
        $val=$redis->get("$keyname");
        print "$val";
}
if($command eq "SET" && $value != ""){
        $redis->set("$keyname" => "$value");
}
if($command eq "INCR"){
 $redis->incr("$keyname");
}

if($command eq "DECR"){
 $redis->decr("$keyname");
}

if($command eq "DECRBY"){
 $redis->decrby("$keyname",$value);
}
if($command eq "DEL"){
$redis->del("$keyname" ) || warn "key doesn't exist";
}
$redis->quit;

Save and Exit;

give permissions to this script.

root@asterisk1:~# chmod 755 /etc/asterisk/redis.pl

Now in Dialplan I call System() Application like this.

exten => _XXX,1,SET(CALLS=${SHELL(/etc/asterisk/redis.pl 1 GET ${CALLERID(num)})})
same => n,NOOP(The Caller:${CALLERID(num)} has ${CALLS} calls in the system)
same => n,Answer()
same => n,System(/etc/asterisk/redis.pl 1 INCR ${CALLERID(num)})
same => n,NOOP(Do some dialplan actions as you want)
...
...
exten => h,1,System(/etc/asterisk/redis.pl 1 DECR ${CALLERID(num)})
exten => h,n,Hangup()

Thats all. Now I can keep realtime track of the active calls for any user/trunk/carrier etc etc from my dialplan. The real beauty of using this shared Redis Memcache store is that I've like 8 asterisk servers, all of them using the same Redis store and all of them are aware of the current number of calls from/to a particular user.

I've also used it to share the Statuses of Queues and Conference rooms residing on special servers with normal IVR servers. Without using this shared store I can only think of using a Database used by all and I believe that doesn't perform well when multiple users are accessing and modifying the same field concurrently especially when the usage is heavy.

8 comments:

  1. Hello,

    Very usefull script ... But i'm asking if i can adapt this script for noSQL DB (Riak or couchDB) ? What do you think ?

    And on this server, i want to store SIP account and others asterisk object (CDR, voicemail). Do you know any driver for noSQL DB ?


    Regards, Loic.

    ReplyDelete
    Replies
    1. Hi Chabert,

      You can definitely create scripts like this to interconnect Asterisk with Riak or CouchDB. I dont think asterisk has any native support for these things.

      Thanks,
      Gohar

      Delete
  2. good article, now i'm trying to use redis working with asterisk servers: IVR asterisk servers, dial asterisk servers.

    ReplyDelete
  3. you say " I've also used it to share the Statuses of Queues and Conference rooms residing on special servers " i want to share information of the status of the queue but i have to do it on special servers ? could you explain a little bit this please , and thank you for your post!

    ReplyDelete
    Replies
    1. My design was something like Queue Server Nodes, Asterisks with only purpose to server Queues or Conferences only.
      The rest of the IVRs and functionality resided on common servers and as soon as a call needed to goto Queue Server it would use the Redis store to See if the same Queue is handled on any Queueing Server.
      Similarly when a call is handled by Queue and hangs up it has its QUEUESTATUS dialplan variable set, but not available on the sender IVR Server, so I used Redis to store that status and on Hanging up of call on Queuing server call returned to resume the dialplan on IVR Server where I retrieved the status of Queue to decide what to do next.
      The Key here is the CAHNNEL variable from the IVR Server which is sent to Queue Server in SIP Header and that is the Key Name in Redis to store the Queue/Conference Statuses in it.

      Delete
    2. Gohar take this opportunity to congratulate you I've seen your other post and has something different talk about unusual subjects of voip.

      you mean you have the same queue into two three or four ..asterisk dedicated queue servers and you use redis to share the device states of the agents to check wich agent are available right ?

      because something similar i want to do , if you are agree you can give me your gmal email ? i will make a proposal to you if there are no problem for you !

      best regards

      Delete
  4. Asterisk group/group count function provides the same functionality

    ReplyDelete