Asterisk Functions in PHPAGI - asterisk

I wanted to use an Asterisk Function "IFTIME" in PHPAGI. The following syntax runs correctly in Dialplan but I have been trying to make it work in PHPAGI.
exten => 1234,1,Set(foo=${IFTIME(16:00-21:00,*,*,*?true:false)})
exten => 1234,2,NoOp(${foo})
So far in PHPAGI this is what I have done
** I am using AGISPEEDY framework, it uses PHPAGI
$agi->agi_exec('Set','fo o=${IFTIME(*,*,*,*?true:false)}');
$result = $agi->get_variable('foo');
$agi->verbose($result);
------result-------
Array(
[code] => 200
[result] => 1
[data] => ${IFTIME(*,*,*,*?true:false)}
)
The above command set the function as a string. I tried changing
this: $agi->agi_exec('Set','foo=${IFTIME(*,*,*,*?true:false)}');
to: $agi->set_variable('foo','${IFTIME(*,*,*,*?true:false)}');
but result is same, it saves ${IFTIME(*,*,*,*?true:false)} as a string.
Any help on how to run an Asterisk Function like IFTIME from PHPAGI would be highly appreciated.

You have use get_full_variable if you use functions.

You are trying to fly to the moon by landing a rocket ship on Mars, what you are doing is pointless.
You are already inside a PHP script, just emulate the same check of IFTIME inside PHP. So, in your case, I will replace the agi_exec command with something like:
$current_timestamp = time();
$current_time = (int)date("Hi", $current_timestamp);
if (($current_time > 1600) && ($current_time < 2100)) {
.. Do some cool PHP here ..
}
This segment wasn't debugged, so it may not work as you think, but you get the idea.
PHPAGI and AGI in general are wonderful tools - when used the right way. You are trying to leverage a Dialplan function/application in order to do something that you would normally do in PHP.

Related

How do i pass multiple variables to writing ODBC function?

I need to insert some data to SQL ftom Asterisk dialplan. I am using ODBC connection and func_odbc.conf file. There are good way to READ several values from SQl, but apparently, i can't find any working solution for inserting several variables to func_odbc function.
I already tried to use NoOp(ODBC_FunctionName(${ARG1},${ARG2},${ARG3})) and it does not work with 'writesql'. Set(${ODBC_Function()={${ARG1},${ARG2},${ARG3}}) is not working either due to Set limited for one name/value pair.
Here is my func_odbc:
[putClientEvaluation]
;${ARG1} - uniqueid
;${ARG2} - operator
;${ARG3} - client
;${ARG4} - rating
;${ARG5} - queue
dsn=voip
writesql=INSERT INTO cc_service_rating(timestamp,callid,operator,client,rating,queue) values(now(),'${SQL_ESC(${ARG1})}','${SQL_ESC(${ARG2})}','${SQL_ESC(${ARG3})}','${SQL_ESC(${ARG4})}','${SQL_ESC(${ARG5})}')
So i need a working way to pass several arguments at once to odbc writesql function.
UPDATE:
Looks like i just have to use VAL instead of ARG:
writesql=INSERT INTO cc_service_rating(timestamp,callid,operator,client,rating,queue) values(now(),'${SQL_ESC(${VAL1})}','${SQL_ESC(${VAL2})}','${SQL_ESC(${VAL3})}','${SQL_ESC(${VAL4})}','${SQL_ESC(${VAL5})}')
But i still get warning from Set:
WARNING[1227][C-00000020]: pbx_variables.c:1155 pbx_builtin_setvar: Set requires one variable name/value pair.
So, how do i do this without using Set?
UPD:
Did this, no warnings now:
macro extension
exten => s,n,Set(operator=${ARG1})
exten => s,n,Set(quename=${ARG2})
exten => s,n,Set(client=${ARG3})
;timestamp,callid,operator,client,rating,queue
exten => s,n,Set(ODBC_putClientEvaluation()=${UNIQUEID},${operator},${client},${MACRO_EXTEN},${quename})
function
writesql=INSERT INTO cc_service_rating(timestamp,callid,operator,client,rating,queue) values(now(),'${VAL1}','${ARG1}','${ARG3}','${VAL2}','${ARG3}')
Not shure why does this work, obviousely i don't understand how ARG and VAL works here, and why putting args in function brackets does not work at all (even with comma screening).
You are using variables incorrect. Please read book article about variables.
Set(ODBC_Function(${ARG1},${ARG2})=${VAL1},"fixed_param",${VAL3})
I think you should try like this:
Set(ODBC_Function()=${VAR1},"fixed_param",${VAL3});

Callfile Set: RECORDINGFILE='whatever', failing

I am using Asterisk 1.4.44-vici built by abuild # build12 on a i686 running Linux on 2013-05-03 19:48:13 UTC
I have tried several ways to make the following work to no avail:
My callfile successfully calls out and records a message.
I want to send a variable that will be used for the recording file name.
In my callfile I have tried the following methods all failing:
Set: RECORDINGFILE=whatever
SetVar: RECORDINGFILE=whatever
Variable: RECORDINGFILE=whatever
Then in my Extension I have the following, watch for wrapping:
[meetme-outbound]
exten => _9XXXXXXXXXXXXXXXXXXXX1NXXNXXXXXX,1,MixMonitor(/var/spool/asterisk/monitorDONE/MP3/${SIPUSERAGENT}${EXTEN:1}${RECORDINGFILE}${STRFTIME(${EPOCH},$
exten => _9XXXXXXXXXXXXXXXXXXXX1NXXNXXXXXX,n,Dial(SIP/voipessential2/${EXTEN:21},,To)
exten => _9XXXXXXXXXXXXXXXXXXXX1NXXNXXXXXX,n,Hangup
THe above will record the file as if RECORDINGFILE, doesn't exist. Very annoying!
What could I be doing wrong? Is there a configuration setting that I am not aware of?
Any help would be greatly appreciated.
Greg Hill
Variable will be set only on one direction of call
To get variable from other direction use
${SHARED(RECORDINGGILE,${BRIDGEPEER})}
http://www.voip-info.org/wiki/view/Asterisk+Detailed+Variable+List

MixMonitor - How to use lame to convert and then remove the source file?

How can I remove the source wav file after the call is finished? If I have to use AGI can I have an example script?
This is how I'm using MixMonitor
exten => s,n,MixMonitor(${source_file}.wav,W(1),lame -V3 ${source_file}.wav ${mp3_from_source}.mp3)
Fails because it is deleted before the conversion.
exten => h,n,System(rm ${source_file}.wav)
How about:
exten => s,n,MixMonitor(${source_file}.wav,W(1),lame -V3 ${source_file}.wav ${mp3_from_source}.mp3 && rm ${source_file}.wav)
and skip the call in h?
Honestly, you need to stop being creative. Just exec the system level calls as separate dial plan lines. One line for mixmonitor, one line for lame, verify the return value of lame, then delete. This is what I do in my applications, and it works perfect. You don't need to combine every step of the conversion process into a single dialplan line.
I use this command line:
/usr/local/bin/lame -b16 --noshort "/var/spool/asterisk/monitor/$1.wav" "/var/www/html/asterisk/calls/$1.mp3"

Solution for "Fatal error: Maximum function nesting level of '100' reached, aborting!" in PHP

I have made a function that finds all the URLs within an html file and repeats the same process for each html content linked to the discovered URLs. The function is recursive and can go on endlessly. However, I have put a limit on the recursion by setting a global variable which causes the recursion to stop after 100 recursions.
However, php returns this error:
Fatal error: Maximum function nesting level of '100' reached,
aborting! in
D:\wamp\www\crawler1\simplehtmldom_1_5\simple_html_dom.php on line
1355
I found a solution here: Increasing nesting function calls limit but this is not working in my case.
I am quoting one of the answers from the link mentioned above. Please do consider it.
"Do you have Zend, IonCube, or xDebug installed? If so, that is probably where you are getting this error from.
I ran into this a few years ago, and it ended up being Zend putting that limit there, not PHP. Of course removing it will let >you go past the 100 iterations, but you will eventually hit the memory limits."
Is there a way to increase the maximum function nesting level in PHP
Increase the value of xdebug.max_nesting_level in your php.ini
A simple solution solved my problem. I just commented this line:
zend_extension = "d:/wamp/bin/php/php5.3.8/zend_ext/php_xdebug-2.1.2-5.3-vc9.dll
in my php.ini file. This extension was limiting the stack to 100 so I disabled it. The recursive function is now working as anticipated.
Another solution is to add xdebug.max_nesting_level = 200 in your php.ini
Rather than going for a recursive function calls, work with a queue model to flatten the structure.
$queue = array('http://example.com/first/url');
while (count($queue)) {
$url = array_shift($queue);
$queue = array_merge($queue, find_urls($url));
}
function find_urls($url)
{
$urls = array();
// Some logic filling the variable
return $urls;
}
There are different ways to handle it. You can keep track of more information if you need some insight about the origin or paths traversed. There are also distributed queues that can work off a similar model.
Rather than disabling the xdebug, you can set the higher limit like
xdebug.max_nesting_level=500
It's also possible to fix this directly in php, for example in the config file of your project.
ini_set('xdebug.max_nesting_level', 200);
Go into your php.ini configuration file and change the following line:
xdebug.max_nesting_level=100
to something like:
xdebug.max_nesting_level=200
on Ubuntu using PHP 5.59 :
got to `:
/etc/php5/cli/conf.d
and find your xdebug.ini in that dir, in my case is 20-xdebug.ini
and add this line `
xdebug.max_nesting_level = 200
or this
xdebug.max_nesting_level = -1
set it to -1 and you dont have to worry change the value of the nesting level.
`
probably happened because of xdebug.
Try commenting the following line in your "php.ini" and restart your server to reload PHP.
  ";xdebug.max_nesting_level"
Try looking in /etc/php5/conf.d/ to see if there is a file called xdebug.ini
max_nesting_level is 100 by default
If it is not set in that file add:
xdebug.max_nesting_level=300
to the end of the list so it looks like this
xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/home/drupalpro/websites/logs/profiler
xdebug.max_nesting_level=300
you can then use #Andrey's test before and after making this change to see if worked.
php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'
php.ini:
xdebug.max_nesting_level = -1
I'm not entirely sure if the value will ever overflow and reach -1, but it'll either never reach -1, or it'll set the max_nesting_level pretty high.
You could convert your recursive code into an iterative code, which simulates the recursion. This means that you have to push the current status (url, document, position in document etc.) into an array, when you reach a link, and pop it out of the array, when this link has finished.
Check recursion from command line:
php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'
if result > 100 THEN check memory limit;
You could try to wiggle down the nesting by implementing parallel workers (like in cluster computing) instead of increasing the number of nesting function calls.
For example: you define a limited number of slots (eg. 100) and monitor the number of "workers" assigned to each/some of them. If any slots become free, you put the waiting workers "in them".
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...
P.S. Change 9999 to any number you want.
Stumbled upon this bug as well during development.
However, in my case it was caused by an underlying loop of functions calling eachother - as a result of continuous iterations during development.
For future reference by search engines - the exact error my logs provided me with was:
Exception: Maximum function nesting level of '256' reached, aborting!
If, like in my case, the given answers do not solve your problem, make sure you're not accidentally doing something along the lines of the following simplified situation:
function foo(){
// Do something
bar();
}
function bar(){
// Do something else
foo();
}
In this case, even if you set ini_set('xdebug.max_nesting_level', 9999); it will still print out the same error message in your logs.
If you're using Laravel, do
composer update
This should be work.
In your case it's definitely the crawler instance is having more Xdebug limit to trace error and debug info.
But, in other cases also errors like on PHP or core files like CodeIgniter libraries will create such a case and if you even increase the x-debug level setting it would not vanish.
So, look into your code carefully :) .
Here was the issue in my case.
I had a service class which is library in CodeIgniter. Having a function inside like this.
class PaymentService {
private $CI;
public function __construct() {
$this->CI =& get_instance();
}
public function process(){
//lots of Ci referencing here...
}
My controller as follow:
$this->load->library('PaymentService');
$this->process_(); // see I got this wrong instead it shoud be like
Function call on last line was wrong because of the typo, instead it should have been like below:
$this->Payment_service->process(); //the library class name
Then I was keeping getting the exceed error message. But I disabled XDebug but non helped. Any way please check you class name or your code for proper function calling.
I had a error when i was installing many plugins So the error 100 showed including the location of the last plugin that i installed C:\wamp\www\mysite\wp-content\plugins\"..." so i deleted this plugin folder on the C: drive then everything was back to normal.I think i have to limit the amount of plug-in i install or have activated .good luck i hope it helps
I had this issue with WordPress on cloud9. It turns out it was the W3 Caching plugin. I disabled the plugin and it worked fine.
Another solution if you are running php script in CLI(cmd)
The php.ini file that needs edit is different in this case. In my WAMP installation the php.ini file that is loaded in command line is:
\wamp\bin\php\php5.5.12\php.ini
instead of \wamp\bin\apache\apache2.4.9\bin\php.ini which loads when php is run from browser
You can also modify the {debug} function in modifier.debug_print_var.php, in order to limit its recursion into objects.
Around line 45, before :
$results .= '<br>' . str_repeat(' ', $depth * 2)
. '<b> ->' . strtr($curr_key, $_replace) . '</b> = '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
After :
$max_depth = 10;
$results .= '<br>' . str_repeat(' ', $depth * 2)
. '<b> ->' . strtr($curr_key, $_replace) . '</b> = '
. ($depth > $max_depth ? 'Max recursion depth:'.(++$depth) : smarty_modifier_debug_print_var($curr_val, ++$depth, $length));
This way, Xdebug will still behave normally: limit recursion depth in var_dump and so on.
As this is a smarty problem, not a Xdebug one!
I had the same problem and I resolved it like this:
Open MySQL my.ini file
In [mysqld] section, add the following line: innodb_force_recovery =
1
Save the file and try starting MySQL
Remove that line which you just added and Save

Function that returns a value in extensions.conf - asterisk

I want to do the following in my extensions.conf in asterisk:
Read in a number entered by a user. - easy
Feed that number into a script which returns a wav file.
This wav file is then played.
I know the system command, but have not been able to figure out a way for it to return a value.
Any help is most welcome,
Thanks,
Sriram.
For such things I use Asterisk AGI. Idea is similar to CGI scripts for Web servers. You can use various languages, but I use Python with pyst: Python for Asterisk library. Such AGI script/program can read or set channel variable and this way communicate with Asterisk dialplan.
Example of such code with pyst agilib:
wav_to_play = 'other.wav'
user_nr = agilib.get_variable('user_entered_number')
if not user_nr:
wav_to_play = 'nothing.wav'
elif user_nr.endswith('0'):
wav_to_play = 'zero.wav'
# ...
agilib.set_variable('wav_selected', wav_to_play)
After saving such code in wav_selector.agi (you must add normal Python header, libs etc) you can use it in dialplan like:
exten => s,n,Set(user_entered_number=5)
exten => s,n,AGI(wav_selector.agi)
exten => s,n,Background((${wav_selected})
One can have the program/script write the value to a file and then use the functions within asterisk such as ReadFile to get the value. This can be done like so:
Within the script:
echo -n ${value} > ${fileName}
From within asterisk:
exten => 0,n,ReadFile(ValueReadFromFile=${fileName},${MAX_FILE_CHAR})
where: ${MAX_FILE_CHAR} is the max. characters that need to be read from the file ${fileName}. The value you want read will be stored in ValueReadFromFile.

Resources