[asterisk-users] Asterisk 1.4.30 is slow sending STDIN to AGI script
Gareth Blades
list-asterisk at skycomuk.com
Wed Apr 28 09:46:31 CDT 2010
Danny Nicholas wrote:
> Can you post the script?
>
Yes private stuff is in a separate file. $mode=start works fine but
answered and completed cause the problem.
I dont know if it is a problem with teh AGI script or just the newer
asterisk reporting it as an error. It doesnt effect functionality but
just gives a lot of console output and logging which is undesireable.
Thanks
Gareth
#!/usr/bin/perl -I /var/lib/asterisk/agi-bin/includes
package Asterisk::AGIwrap;
use strict;
use base 'Asterisk::AGI';
sub set_variable
{
my ($self, %vars) = @_;
while (my($var,$val) = each %vars)
{
if (!defined($val))
{ warn "AGI->set_variable: not setting '$var' because value
was undef\n"; next; }
#warn "AGI->set_variable('$var','$val')\n";
$self->SUPER::set_variable($var, $val);
}
}
package main;
use strict;
our $application = "service_nts_nextgen";
our $subagent = "AGI - $application";
open(OLD_STDERR,">&STDERR") or die "Failed to save STDERR";
open(STDERR,">>/var/log/agi_$application.err") or die "Failed to
redirect STDERR";
my $settings = require '/var/lib/asterisk/agi-bin/skycom_gw_settings.pl';
our $gatewayID = $settings->{'gatewayID'};
my ($dbname, $dbhost, $dbport, $dbuser, $dbpass) =
@{%{$settings->{'db'}}}{'name','host','port','user','pass'};
my $db;
eval
{
use DBI;
$db = DBI->connect("DBI:mysql:$dbname:$dbhost:$dbport", $dbuser,
$dbpass, $settings->{'dbopt'}) || die "Cannot connect to database:
$DBI::errstr";
our $AGI = new Asterisk::AGIwrap;
print STDERR scalar localtime, " RUNNING:$0 ", (map {"\"$_\" "}
@ARGV), "\n";
our $mode = $ARGV[0];
my %ARG = ();
if ($mode =~ /mode=(.*)/)
{
$ARG{'mode'} = $mode = $1;
foreach my $arg (@ARGV)
{
$arg =~ /^(\w+)=(.*)$/ || next;
$ARG{$1} = $arg = $2;
}
}
our $not_recognised = 0;
my $func;
if ($mode eq "start")
{
$func = require
'/var/lib/asterisk/agi-bin/service_nts_nextgen-start.pl';
&$func('db'=>$db, 'AGI'=>$AGI, 'settings'=>$settings);
}
elsif ($mode eq "answered")
{
my $uniqueID = $ARGV[1];
my $uniqueIDB = $ARGV[2];
my $destination = $ARGV[3];
my $destination_type = $ARGV[4];
my $destination_args = $ARGV[5];
my $destination_carrier = $ARGV[6];
$destination =~ s/^00//; # International
$destination =~ s/^0([1-9]+)/44$1/; # UK
my $args = {
#'destination_type_id' => '"'.$destination_type.'"',
'answer_time' => 'NOW()',
'answer_epoch' => 'UNIX_TIMESTAMP()',
'uniqueIDB' => '"'.$uniqueIDB.'"',
'ddi' => '"'.$destination.'"',
'carriernameID' => carriernameID($destination_carrier)
};
if ($destination_type)
{ $args->{'destination_type_id'} = '"'.$destination_type.'"'; }
if ($destination_args ne '') { $args->{'destination_args'} =
'"'.$destination_args.'"'; }
if (defined($ARG{'params'}))
{ $args->{'extra_params'} =
$db->quote(urlstr_to_miniserial($ARG{'params'})); }
&updateCDR($uniqueID,$args,$db);
}
elsif ($mode eq "completed")
{
my $uniqueID = $ARGV[1];
my $status = $ARGV[2];
my $failedpredial = $ARGV[4];
if ($uniqueID eq "") { $uniqueID = $ARGV[3]; }
if ($status eq "" && $failedpredial ne "1") { $status = "FAILED"; }
my $destination_type = ($ARGV[6] =~ /^\d+$/ ? $ARGV[6] : 0);
my $dest_arg = $ARGV[7];
my $connect_epoch = $ARGV[8] || 0;
my $args = {
'end_time' => 'NOW()',
'end_epoch' => 'UNIX_TIMESTAMP()',
'duration' => '(UNIX_TIMESTAMP(NOW()) -
UNIX_TIMESTAMP(start_time))',
'carriernameID' => carriernameID($ARGV[5]),
'connect_epoch'=>$connect_epoch,
($destination_type ?
('destination_type_id'=>$destination_type) : ()),
};
if (defined($ARG{'params'}))
{ $args->{'extra_params'} =
$db->quote(urlstr_to_miniserial($ARG{'params'})); }
if ($status eq "VOICEMAIL")
{
$args->{'destination_type_id'} = 3;
$status = "ANSWER";
}
if ($status eq "ANNOUNCEMENT")
{
$args->{'destination_type_id'} = 6;
$status = "ANSWER";
}
if ($destination_type == 1)
{
if ($dest_arg =~ /^\d+$/)
{
if ($dest_arg =~ /^00/)
{ $dest_arg =~ s/^00//; }
elsif ($dest_arg =~ /^0[1-9]/)
{ $dest_arg =~ s/^0/44/; }
$args->{'ddi'} = $db->quote($dest_arg);
}
}
elsif ($destination_type > 1)
{ $args->{'destination_args'} = $db->quote($dest_arg); }
if (!$failedpredial) { $args->{'disposition'} = '"'.$status.'"'; }
if ($status eq "ANSWER")
{
my @existing_updates = keys(%$args);
$args->{'answer_epoch'} =
"COALESCE(answer_epoch,UNIX_TIMESTAMP())";
$args->{'start_epoch'} = "LEAST(start_epoch,answer_epoch)";
# } if date puts time back a few seconds, this would cause us to record
an answer
$args->{'start_time'} = "FROM_UNIXTIME(start_epoch)";
# } time/epoch earlier than the start time, so fix the start time/epoch
$args->{'answer_time'} = "FROM_UNIXTIME(answer_epoch)";
$args->{'end_time'} = "NOW()";
$args->{'end_epoch'} = "UNIX_TIMESTAMP()";
$args->{'disposition'} = "'ANSWER'";
$args->{'duration'} = "end_epoch-start_epoch";
$args->{'duration_billable'} = "end_epoch-answer_epoch";
$args->{'.order'} =
['answer_epoch','answer_time','start_epoch','start_time','end_time','end_epoch','disposition','duration','duration_billable', at existing_updates];
#$args->{'duration_billable'} = '(UNIX_TIMESTAMP(NOW()) -
UNIX_TIMESTAMP(answer_time))';
}
print STDERR scalar localtime, " *** CALL COMPLETED:
".join(',', at ARGV)." ***\n";
&updateCDR($uniqueID, $args,$db);
}
elsif ($mode eq "ida_ddi")
{
my ($ddi, $uniqueID) = @ARG{'ddi','uniqueID'};
$ddi =~ /^\d+$/ || die "Bad ddi '$ddi'\n";
$func = require
'/var/lib/asterisk/agi-bin/service_nts_nextgen-start.pl';
&$func('db'=>$db, 'AGI'=>$AGI, 'settings'=>$settings,
'selector'=>{'mode'=>'ida_ddi', 'args'=>{'ddi'=>$ddi}});
($ddi =~ s/^00//) || ($ddi =~ s/^0([1-9])/44$1/);
&updateCDR($uniqueID, {'ddi'=>$ddi}, $db);
}
elsif ($mode eq "getivr")
{
my ($ivrID) = @ARGV[1];
$ivrID =~ /^\d+$/ || die "Bad ivrID '$ivrID'\n";
$func = require
'/var/lib/asterisk/agi-bin/service_nts_nextgen-start.pl';
&$func('db'=>$db, 'AGI'=>$AGI, 'settings'=>$settings,
'selector'=>{'mode'=>'ivrmenu', 'args'=>{'ivrID'=>$ivrID}});
}
elsif ($mode eq "getivrchoice")
{
my ($ivrID, $userchoice) = @ARGV[1,2];
$ivrID =~ /^\d+$/ || die "Bad ivrID '$ivrID'\n";
$userchoice =~ /^\d+$/ || die "Bad userchoice '$ivrID'\n";
$func = require
'/var/lib/asterisk/agi-bin/service_nts_nextgen-start.pl';
&$func('db'=>$db, 'AGI'=>$AGI, 'settings'=>$settings,
'selector'=>{'mode'=>'ivrchoice', 'args'=>{'ivrID'=>$ivrID,
'userchoice'=>$userchoice}});
}
};
print STDERR scalar localtime, " Gateway $gatewayID app
error(app=$application, file=$0): $@\n" if $@;
open(STDERR,">&OLD_STDERR") or die "Failed to restore STDERR";
# the end
sub updateCDR
{
my ($uniqueid, $args, $db) = @_;
my @required = ();
foreach my $field (@required)
{
if (!defined($args->{$field}))
{
logMessage(10, $subagent, "updateCDR: required field
missing: ".$field);
return 0;
}
}
my @updates = ();
my @update_order = (exists($args->{'.order'}) ?
@{$args->{'.order'}} : keys %$args);
delete ($args->{'.order'});
foreach my $field (@update_order)
{
next if !exists($args->{$field});
push (@updates, "$field=".$args->{$field});
delete ($args->{$field});
}
die "no CDR data" if !@updates;
my $query = "UPDATE call_detail_log SET ".join(",", at updates)."
WHERE uniqueID='$uniqueid'";
print STDERR scalar localtime, " $query\n";
$db->do($query);
return 1;
}
sub carriernameID
{
my $name = shift(@_) || return 0;
return $db->selectcol_arrayref("SELECT ID FROM
call_detail_log_enum_carriername WHERE name=?",{},$name)->[0] || eval
{
my $rows = $db->do("INSERT INTO
call_detail_log_enum_carriername SET name=?",{},$name);
return ($rows > 0 ? $db->{'mysql_insertid'} : 0);
};
}
sub urlstr_to_miniserial
{
my $urldec = sub { my ($url) = @_; $url =~ s/(\+|%([A-Z0-9]{2}))/$1
eq '+'?' ':chr(hex($2))/eg; return $url; };
my $dec_hash = sub { return map { $_ =~ /^(.+?)(=(.*))?$/ &&
(&$urldec($1),&$urldec($3)) } split(/&/,shift(@_)); };
return join('',map { length($_).':'.$_ } &$dec_hash(@_));
}
More information about the asterisk-users
mailing list