Asterisk AGI Programming
Asterisk AGI Programming
@# do I use
Windows on my notebook?
While I would prefer to use Linux on my notebook, it will
introduce some interoperability issues when going to
business meetings abroad.
The notebook had a license on it, which if removed will not
be supported by IBM.
Too much work, no time to start installing everything from
scratch.
99% of my clients use Exchange, so using anything other
than Outlook messes e-Mails like hell.
If you still have a problem with it, you are welcome to take
it outside with me after the lecture ;-)
Welcome to Asterisk
Asterisk is a complete PBX in software. It
runs on Linux, BSD and MacOSX and
provides all of the features you would
expect from a PBX and more. Asterisk does
voice over IP in many protocols, and can
interoperate with almost all standards-based
telephony equipment using relatively
inexpensive hardware.
AGI Cont
Once of the advantages of utilizing the AGI
interface is the ability to develop proprietary
applications and platforms while utilizing an
dually licensed, Open Sourced, PBX core.
While any change inflicted upon an Asterisk
internal module or application MUST be
contributed and disclaimed back to Digium,
AGI applications are external from Asterisk and
do not require such disclaiming and
contribution.
AGI Basics
AGI is loosely based upon the old CGI
model of operation. Asterisk
communicates with AGI scripts via
STDIN/STDOUT.
Anything sent from Asterisk to the AGI
script will be considered as STDIN to the
AGI script.
Anything sent from the AGI script back to
Asterisk will be considered as STDOUT
of the AGI script.
4.
Asterisk forks out and runs the application is its own user
space.
All channel variables that were available to the Asterisk
dial-plan, prior to executing the AGI script are available to
the AGI script.
Asterisk sends out a bunch of information that must be
handled before the script actually starts running. This
information usually can be completed disregarded,
but it is important to handle it.
Your logic runs at this point.
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
_XXX.,1,Answer
_XXX.,n,Set(TIMEOUT(digit)=2)
; Set Digit Timeout to 2 seconds
_XXX.,n,Set(TIMEOUT(response)=5)
; Set Response Timeout to 5 seconds
_XXX.,n,SetCDRuserfield(${statusid})
_XXX.,n,Wait(0.5)
_XXX.,n,ResetCDR(vw)
_XXX.,n,AGI(ServiceCheckBilling.php)
_XXX.,n,Gotoif($["${billingType}" = "0"]?NoAuthOn0:Authorization)
_XXX.,n(NoAuthOn0),AGI(ServiceStart.php)
_XXX.,n,AGI(PassOperatorToMeetMeRoom)
_XXX.,n(Authorization),Gotoif($["${billingType}" = "1"]?NoAuthOn1:AuthorizationCC)
_XXX.,n(NoAuthOn1),AGI(ServiceStart.php)
_XXX.,n,AGI(PassOperatorToMeetMeRoom)
_XXX.,n(AuthorizationCC),Gotoif($["${billingType}" = "3"]?Auth3Party:AuthCollect)
_XXX.,n(Auth3Party),AGI(ServiceStart.php)
_XXX.,n,AGI(ThirdPartyOperatorCallSecondLeg.php)
_XXX.,n,Hangup()
_XXX.,n(AuthCollect),Gotoif($["${billingType}" = "4"]?AuthRegular:EndScript)
_XXX.,n(AuthRegular),AGI(ServiceStart.php)
_XXX.,n,AGI(PassOperatorToMeetMeRoom.php)
_XXX.,n(EndScript),NoOp
AGI/Dialplan Balancing
One of the first mistakes most AGI programmers tend to
do is to initiate a HUGE AGI script that does everything,
instead of using the dialplan state machine.
This is especially problematic when you are programming
in a VM environment such as JAVA/C#.
When possible, make your AGI scripts as short as
possible, down to an atomic level, have them simply set a
channel variable, and then initiate another AGI script
according to the result of the previous one.
If your AGI script becomes long and cluttered, you must
be doing something wrong and in the words of a friend
of mine: you are in desperate need of re-factoring.
PHPAGI Wrapping
Most AGI programmers tend to write their
AGI scripts as self enclosed scripts this
usually leads to code duplication and hard
code maintenace.
By utilizing the channel variables as a
methodology to pass variable from one
script to another, is it possible to write
your own AGI script invoker, thus,
making your AGI scripts more stream
lined.
Wrapper Example
#!/usr/bin/php -q
<?php
require "phpagi/phpagi.php";
define_syslog_variables();
// Initiate an array for local channel variable keeping
$agiVariables = array();
// Initiate an AGI instance
$agiWrapper = new AGI("/var/lib/asterisk/agi-bin/include/phpagi.conf");
openlog("[".$sessionId['data']."/".$argv[1]."]", LOG_PID | LOG_PERROR,
LOG_LOCAL2);
// Lets parse the parameters from AGI execution
$agiParameters = $argv[1];
$agiList=array();
$agiList=explode("^",$agiParameters);
syslog(LOG_INFO, "agiParameters: ".$argv[1]);
// Now that we have the AGI parameters list, lets see what we are going to execute
// echo "Executing ".$agiList[0]." AGI\n";
syslog(LOG_INFO, "Initiating : ".$agiList[0]." execution");
include "/var/lib/asterisk/agi-bin/modules/".$agiList[0].".inc.php";
?>
agiSetSessionId.php
#!/usr/bin/php -q
<?php
require "phpagi/phpagi.php";
$sessionId = uniqid();
$agiWrapper
= new AGI("/var/lib/asterisk/agi-bin/include/phpagi.conf");
$agiWrapper->set_variable("session_id",$sessionId);
$call_cli = $agiWrapper->get_variable(CALLERIDNUM");
define_syslog_variables();
openlog("[".$sessionId."/".basename($argv[0],".php")."]", LOG_PID | LOG_PERROR,
LOG_LOCAL2);
syslog(LOG_INFO, "Creating session: [".$sessionId."] for CLID: ".$call_cli['data']);
?>
We run this script externally from the wrapper due to the fact
that it would feed information into the PHPAGI wrapper,
such as the session ID.
Randomize.inc.php
<?php
// Lets randomize a number from 1 to 15
$RandomNumber=rand(1, 15);
$session_id = $agiWrapper->get_variable("session_id");
syslog(LOG_INFO, "Starting Session for ".$session_id['data']);
$agiWrapper->set_variable("sillyFile",$RandomNumber);
syslog(LOG_INFO, "Setting sillyFile ENVVAR as: ".$RandomNumber);
?>
Syslog says
Manual Interaction
Manual interaction with the Asterisk Manager can be
performed by performing a telnet to port 5038, and
interacting directly.
Each interaction with the manager looks like this:
Manager Commands
AbsoluteTimeout: Set Absolute Timeout (privilege: call,all)
ChangeMonitor: Change monitoring filename of a channel
(privilege: call,all)
Command: Execute Command (privilege: command,all)
Events: Control Event Flow
ExtensionState: Check Extension Status (privilege: call,all)
GetVar: Gets a Channel Variable (privilege: call,all)
Hangup: Hangup Channel __(privilege: call,all)
IAXpeers: List IAX Peers (privilege: system,all)
ListCommands: List available manager commands
Logof: Logoff Manager
MailboxCount: Check Mailbox Message Count (privilege: call,all)
MailboxStatus: Check Mailbox (privilege: call,all)
Monitor: Monitor a channel (privilege: call,all)
Originate: Originate Call (privilege: call,all)
ParkedCalls: List parked calls
Ping: Ping
Questions anyone?
For more information about Asterisk
please refer to http://www.asterisk.org.il
For information about Asterisk
programming and Open Source VoIP
revolution, please refer to
http://www.voip-info.org
PHP/MySQL/PERL Talents are welcome
to hand in your CVs after the lecture.
Thank you