Packt Publishing Community Experience, Distilled

Asterisk Gateway Interface Scripting with PHP

HomeBooksSupportFreeAuthorsAward
WELCOME YOUR ACCOUNT NEWSLETTERS ARTICLES ABOUT US

 
Article Network FAQ

Want to know more about Packt's Article Network? Interested in contributing your article ideas?

Please visit our FAQ for more information.


See More

BOOK
AJAX and PHP: Building Responsive Web Applications
AJAX and PHP: Building Responsive Web Applications
See More

SEARCH

Search our Site


A Primer to AGI: Asterisk Gateway Interface

This article by Nir Simionovich is all about AGI (Asterisk Gateway Interface)—its working, its three types, and the different frameworks.

Asterisk AGI enables an IVR developer to develop IVR structures that are sometimes, bordering on the absurd, as applications tend to become more and more complex by using AGI. However, there are some scenarios where common dialplan practices are no longer applicable, and the use of an external logic is a must. Enter AGI!


See More
 
Asterisk Gateway Interface Scripting with PHP

In this article by Nir Simionovich, we will develop our first ever AGI script using PHP scripting language. This article deals with the most basic elements of AGI scripting and the information contained within. So, take time to familiarize yourself with this article, especially if you intend to use a language different from PHP.

PHP-CLI vs PHP-CGI

Most Linux distributions include both versions of PHP when installed, especially if you are using a modern distribution such as CentOS or Mandriva. When writing AGI scripts with PHP, it is imperative that you use PHP-CLI, and not PHP-CGI.

Why is this so important? The main issue is that PHP-CLI and PHP-CGI handle their STDIN (standard input) slightly differently, which makes the reading of channel variables via PHP-CGI slightly more problematic.

The php.ini configuration file

The PHP interpreter includes a configuration file that defines a set of defaults for the interpreter. For your scripts to work in an efficient manner, the following must be set—either via the php.ini file, or by your PHP script:

ob_implicit_flush(false); 
set_time_limit(5);
error_log = filename;
error_reporting(0);

The above code snippet performs the following:

Directive

Description

ob_implicit_flush(false);

Sets your PHP output buffering to false, in order to make sure that output from your AGI script to Asterisk is not buffered, and takes longer to execute

·         set_time_limit(5);

Sets a time limit on your AGI scripts to verify that they don't extend beyond a reasonable time of execution; there is no rule of thumb relating to the actual value; it is highly dependant on your implementation

Depending on your system and applications, your maximum time limit may be set to any value; however, we suggest that you verify your scripts, and are able to work with a maximum limit of 30 seconds.

·         error_log = filename;

Excellent for debugging purposes; always creates a log file

·         error_reporting(E_NONE);

Does not report errors to the error_log; changes the value to enable different logging parameters; check the PHP website for additional information about this

AGI script permissions

All AGI scripts must be located in the directory /var/lib/asterisk/agi-bin, which is Asterisk's default directory for AGI scripts. All AGI scripts should have the execute permission, and should be owned by the user running Asterisk. If you are unfamiliar with these, consult with your system administrator for additional information.

The structure of a PHP based AGI script

Every PHP based AGI script takes the following form:

#!/usr/bin/php -q 
<?
$stdin = fopen(‘php://stdin’, ‘r’);
$stdout = fopen(‘php://stdout’, ‘w’);
$stdlog = fopen(‘my_agi.log’, ‘w’);


/* Operational Code starts here */
..
..
..
?>

Upon execution, Asterisk transmits a set of information to our AGI script via STDIN. Handling of that input is best performed in the following manner:

#!/usr/bin/php -q 
<?
$stdin = fopen(‘php://stdin’, ‘r’);
$stdout = fopen(‘php://stdout’, ‘w’);
$stdlog = fopen(‘my_agi.log’, ‘w’);

/* Handling execution input from Asterisk */

while (!feof($stdin))
{
$temp = fgets($stdin);
$temp = str_replace("\n","",$temp);
$s = explode(":",$temp);
$agivar[$s[0]] = trim($s[1]);
if $temp == "")
{
break;
}
}

/* Operational Code starts here */
..
..
..
?>

Once we have handled our inbound information from the Asterisk server, we can start our actual operational flow.

Communication between Asterisk and AGI

The communication between Asterisk and an AGI script is performed via STDIN and STDOUT (standard output). Let's examine the following diagram:

In the above diagram, ASC refers to our AGI script, while AST refers to Asterisk itself.

As you can see from the diagram above, the entire flow is fairly simple. It is just a set of simple I/O queries and responses that are carried through the STDIN/STDOUT data streams.

Let's now examine a slightly more complicated example:

The above figure shows an example that includes two new elements in our AGI logic—access to a database, and to information provided via a web service. For example, the above image illustrates something that may be used as a connection between the telephony world and a dating service. This leads to an immediate conclusion that just as AGI is capable of connecting to almost any type of information source, depending solely on the implementation of the AGI script and not on Asterisk, Asterisk is capable of interfacing with almost any type of information source via out-of-band facilities.

Enough of talking! Let's write our first AGI script.




Asterisk Gateway Interface 1.4 and 1.6 Programming
 
Asterisk Gateway Interface 1.4 and 1.6 Programming  Design and develop Asterisk-based VoIP telephony platforms and services using PHP and PHPAGI
  • Develop voice-enabled applications utilizing the collective power of Asterisk, PHP, and the PHPAGI class library
  • Learn basic elements of a FastAGI server utilizing PHP and PHPAGI
  • Develop new Voice 2.0 mesh-ups using the Asterisk Manager
  • Add Asterisk application development skills to your development arsenal, enriching your market offering and experience
  • Up to date for Asterisk version 1.6 and covers all previous versions
http://www.packtpub.com/asterisk-gateway-interface-programming/book




The AGI Hello-World program

Just as with any other programming language, we shall begin our journey with a simple "Hello-World" AGI script.

In order to make our life easier, we shall use an astRead function and an astWrite function that will help us read and write information, to and from Asterisk in a more efficient manner.

function astRead() 
{
global $stdin, $debug, $stdlog;
$input = str_replace("\n", "", fgets($stdin, 4096));
if ($debug) fputs($stdlog, "read: $input\n");
return $input;
}

function astWrite($agiCommand)
{
global $debug, $stdlog;
if ($debug) fputs($stdlog, "write: $agiCommand\n");
echo $agiCommand."\n";
}

The astRead function reads information from a global variable, indicated by the $in variable. The $in variable will simply indicate our STDIN stream. The astWrite function writes its $agiCommand directly to STDOUT, simply passing the AGI command directly to Asterisk.

Let's combine everything together:

#!/usr/bin/php -q 
<?
ob_implicit_flush(false);
set_time_limit(6);

$stdin = fopen(‘php://stdin’, ‘r’);
$stdlog = fopen(‘my_agi.log’, ‘w’);

$debug = false;

/* Read input from Asterisk and output via $astOutput */
function astRead()
{
global $stdin, $debug, $stdlog;
$astOutput = str_replace("\n", "", fgets($stdin, 4096));
if ($debug) fputs($stdlog, "read: $input\n");
return $astOutput ;
}


/* Write AGI command to Asterisk */
function astWrite($agiCommand)
{
global $debug, $stdlog;
if ($debug) fputs($stdlog, "write: $agiCommand\n");
echo $agiCommand."\n";
}

/* Handling execution input from Asterisk */

while (!feof($stdin))
{
$temp = fgets($stdin);
$temp = str_replace("\n","",$temp);
$s = explode(":",$temp);
$agivar[$s[0]] = trim($s[1]);
if ($temp == "")
{
break;
}
}

/* Operational Code starts here */

..
..
..


/* Finalization of AGI script and clean-ups */

fclose ($stdin);
fclose ($stdlog);
exit(0);

?>

The above code snippet will form our basic AGI script construct. We've now defined our stream handling functions and our Asterisk input execution handling, as we get ready to start our first AGI script.

Our first script will make use of the AGI command STREAM FILE. Another command that we shall use will be SAY NUMBER.

/* Operational Code starts here */

/* Playback the demo-congrats.gsm file from the
* directory /var/lib/asterisk/sounds/
*/

astWrite("STREAM FILE demo-congrats #");
astRead();

/* Say the number 123456 */
astWrite("SAY NUMBER 123456 #");
astRead();

This AGI code performs a fairly simplistic function—upon execution, it plays back the demo-congrats.gsm file, followed by the number 123456. Ok, that's simple enough; so let's put everything together:

File: helloworld.php

#!/usr/bin/php -q 
<?
ob_implicit_flush(false);
set_time_limit(6);

$stdin = fopen(‘php://stdin’, ‘r’);
$stdlog = fopen(‘my_agi.log’, ‘w’);

$debug = false;

/* Read input from Asterisk and output via $astOutput */
function astRead()
{
global $stdin, $debug, $stdlog;
$astOutput = str_replace("\n", "", fgets($stdin, 4096));
if ($debug) fputs($stdlog, "read: $input\n");
return $astOutput ;
}


/* Write AGI command to Asterisk */
function astWrite($agiCommand)
{
global $debug, $stdlog;
if ($debug) fputs($stdlog, "write: $agiCommand\n");
echo $agiCommand."\n";
}

/* Handling execution input from Asterisk */
$agivar = array();
while (!feof($stdin))
{
$temp = fgets($stdin);
$temp = str_replace("\n","",$temp);
$s = explode(":",$temp);
$agivar[$s[0]] = trim($s[1]);
if ($temp == "")
{
break;
}
}

/* Operational Code starts here */

/* Playback the demo-congrats.gsm file from the
* directory /var/lib/asterisk/sounds/
*/

astWrite("STREAM FILE demo-congrats #");
astRead();

/* Say the number 123456 */
astWrite("SAY NUMBER 123456 #");
astRead();

/* Finalization of AGI script and clean-ups */

fclose ($stdin);
fclose ($stdlog);
exit(0);

?>

In order to execute our AGI script, we are required to define an extension in our extensions.conf configuration file, and indicate the execution of our script from there. The following is an extract from the"default" context of my Asterisk server. You may insert these into any other context or extension, depending on your Asterisk server configuration:

exten => 999,1,Answer
exten => 999,n,Wait(0.5)
exten => 999,n,AGI(helloworld.php)
exten => 999,n,Hangup()

This code snippet will add a new extension named 999 to your dialplan. When this extension is dialed, your AGI script will be invoked. As your script is executed, the following can be observed on the Asterisk CLI console:

Note that as your AGI script is being executed, the only thing you will see on the CLI is the result of the AGI command, and not the actual execution of the AGI script. Also note that CLI output may vary, depending on your configuration.

AGI debugging

Asterisk provides a means of debugging AGI Scripts as these are executed. In order to use the AGI debugger, you need to have access to Asterisk's CLI interface, and issue the following command:

agi debug

As your script is executed with debug mode enabled, your CLI output would look like this:

As you can see, the example in the preceding screenshot shows the full execution of the AGI script, including the initial information sent from Asterisk to the AGI script. Information traversing from Asterisk to our AGI script is prefixed with the AGI Tx >> marking, while information from our AGI script to Asterisk is prefixed with the AGI Rx >> marking. Although this may look weird, it is perfectly logical when examined from Asterisk's point-of-view.

Disabling AGI debug mode is done using the command:

agi debug off

If you have enabled AGI debugging, it is imperative that you turn it off once you have completed your debug session. Debug mode outputs much information to the Asterisk console and log files, causing your Asterisk performance to be degraded.

Summary

Congratulations! You have just written your first Asterisk AGI script. While the example that we saw previously was shown using the PHP scripting language, I am confident that you will be able to translate these examples into the programming language of your choice.

If you are an experienced programmer, then I urge you to implement something different with AGI. If you are familiar with the activation of web services via CURL, try to write an AGI script to read information(like the weather) from a website and to read it out. Another option is to interface your AGI script with a database, create a username/password IVR script, and let your imagination go wild!





Asterisk Gateway Interface 1.4 and 1.6 Programming
 
Asterisk Gateway Interface 1.4 and 1.6 Programming  Design and develop Asterisk-based VoIP telephony platforms and services using PHP and PHPAGI
  • Develop voice-enabled applications utilizing the collective power of Asterisk, PHP, and the PHPAGI class library
  • Learn basic elements of a FastAGI server utilizing PHP and PHPAGI
  • Develop new Voice 2.0 mesh-ups using the Asterisk Manager
  • Add Asterisk application development skills to your development arsenal, enriching your market offering and experience
  • Up to date for Asterisk version 1.6 and covers all previous versions
http://www.packtpub.com/asterisk-gateway-interface-programming/book


About the Author

Nir Simionovich has been involved with the open-source community in Israel since 1997. His involvement with the open-source community started back in 1997, when he was a student in the Technion, Israel's Technology Institute in Haifa. Nir quickly became involved in organizing open-source events and promoting usage of Linux and open-source technologies in Israel.

In 1998, Nir started working for an IT consulting company (artNET experts Ltd.), where he introduced Linux-based solutions for enterprises and banks. By 2000, Nir had become a SAIR/GNU-certified Linux trainer and Administrator, slowly educating the future generations of Linux admins.

In 2001, Nir moved to the cellular content market, working for a mobile content delivery company (m-Wise Inc.—OTC.BB: MWIS.OB). During his commission atm-Wise, Nir successfully migrated a company that was built purely on Windows 2000 and ColdFusion to open-source technologies, such as Mandrake Linux (today Mandriva), Apache Tomcat, and Kannel (open-source SMS/WAP gateway).

By 2006, Nir had co-founded Atelis (Atelis PLC—AIM: ATEL). Atelis is a Digium distributor and integrator. During the course of 2006, Nir developed an Asterisk-based international operator services platform for Bezeq International, which had replaced a Nortel DMS-300 switch. This platform is currently in use by Bezeq International in Israel, serving over 4000 customers a day.

In mid 2007, Nir left Atelis to become a freelance Asterisk promoter and consultant. Nir currently provides Asterisk consulting and development services to various companies, ranging from early-stage start-up companies, through VoIP service providers and VoIP equipment vendors. In his spare time, Nir is the founder of the Israeli Asterisk users group, the website maintainer of the group and an Asterisk developer, dealing mainly with the localization aspects of Asterisk to Israel.

Coming to 2008, Nir's company (Greenfi eld Technologies Ltd) won the Digium Innovation award at AstriCon 2008, in the pioneer division—for its implementation of a phone-based prayer system, allowing people from around the world to pray at the western wall in Jerusalem.

Nir can be reached at nirs@greenfieldtech.net or through his website http://www.greenfieldtech.net.


Books from Packt

AsteriskNOW
AsteriskNOW

Building Telephony Systems with OpenSER
Building Telephony Systems with OpenSER

Joomla! Web Security
Joomla! Web Security

Learning Nagios 3.0
Learning Nagios 3.0

Linux Thin Client Networks Design and Deployment
Linux Thin Client Networks Design and Deployment

Learning FreeNAS
Learning FreeNAS

Lighttpd
Lighttpd

Zenoss Core Network and System Monitoring
Zenoss Core Network and System Monitoring




 
Article Network


Packt Article Network

Visit Packt's Article Network, for all the latest quality, relevant and free content.
See More



NEWSLETTER

Sign up for updates, offers, free downloads and you could win an iPod Shuffle.
Subscription center
 




© Packt Publishing Ltd 2010

RSS