[asterisk-users] Asterisk 1.4.30 is slow sending STDIN to AGI script

Danny Nicholas danny at debsinc.com
Wed Apr 28 10:14:57 CDT 2010


Darn, that should have worked.  The "improvement" from 1.4.22 to 1.4.23+
basically requires that every "print STDOUT" line be followed by a <STDIN>
to make util.c not choke when doing commands/setting variables.  I wonder
how this "rewrite" would work?
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; }
         print STDOUT "SET VARIABLE $var \"$val\" \r\n";
         <STDIN>;
       }
   }

-----Original Message-----
From: asterisk-users-bounces at lists.digium.com
[mailto:asterisk-users-bounces at lists.digium.com] On Behalf Of Gareth Blades
Sent: Wednesday, April 28, 2010 10:05 AM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] Asterisk 1.4.30 is slow sending STDIN to AGI
script

You mean as in :- ?

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);
         <STDIN>;
       }
   }

It didnt work. The AGI script hung the dialplan before attempting to dial

Thanks

Danny Nicholas wrote:
> Just a hunch - add <STDIN>; after line 15 and give it a whirl.
> 
> -----Original Message-----
> From: asterisk-users-bounces at lists.digium.com
> [mailto:asterisk-users-bounces at lists.digium.com] On Behalf Of Gareth
Blades
> Sent: Wednesday, April 28, 2010 9:47 AM
> To: Asterisk Users Mailing List - Non-Commercial Discussion
> Subject: Re: [asterisk-users] Asterisk 1.4.30 is slow sending STDIN to AGI
> script
> 
> 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_epo
> ch','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(@_));
>    }
> 
> 
> 


-- 
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --
New to Asterisk? Join us for a live introductory webinar every Thurs:
               http://www.asterisk.org/hello

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/asterisk-users




More information about the asterisk-users mailing list