[Asterisk-Users] why $cdr{'CALLERID'} and $cdr{'DNID'} are empty in
perl agi connected with asterisk manager
Kamran Ahmad
p_kami at yahoo.com
Mon Jul 18 05:20:11 MST 2005
hello perl experts
i am working with "ast-rad-acc.pl" from
http://www.voip-info.org/tiki-index.php?page=PortaOne+Radius+auth
i dont know why $cdr{'DNID'} and $cdr{'CALLERID'}
under 'sub send_acc {' are empty. i m successfully
connected with asterisk manager and when call i hangup
my perl application is getting that all other thing
are ok but i dont know why only these two variables
are not working. other variables like CALLID,
ACCOUNTCODE, etc are ok but these two DNID and
CALLERID are empty
here is the code i am using with asterisk-CVS
#!/usr/bin/perl
#
# Based on http://mail.newmmc.com/~wsmith/astcdr
author is unknown,
# found here
http://www.voip-info.org/wiki-Asterisk+AGI
#
# RADIUS Accounting By
# (c)2004 Porta Software Ltd. www.portaone.com
# Oleksandr Kapitanenko <kapitan at portaone.com>
#
use strict;
use Asterisk::Manager;
use Sys::Syslog;
use POSIX;
use Config::IniFiles;
use Authen::Radius;
Authen::Radius->load_dictionary;
# Lock file
#
my $lock_file = '/var/run/ast-rad-acc.pid';
# Config vars
#
my $runas_user = 'nobody';
my $ast_hostname = 'localhost';
my $ast_username = 'test';
my $ast_password = 'test';
my $monitor_dir = '/var/spool/asterisk/monitor';
# Read global RADIUS configuratuin from
extensions.conf
#
# I havte doing that but Asterisk manager interface
can not read global variables
#
my $config_dir = '/usr/local/etc/asterisk';
# Globals
#
my %channels;
my ($rad_serv, $rad_sec, $nas_ip);
# Check if already running
#
if( -e $lock_file ) {
open(PID,$lock_file);
my $pid=<PID>;
close PID;
chomp $pid;
if( !-e "/proc/$pid" ) {
print STDERR "Lock file present, but no process
with pid=$pid.\n";
die "Can't delete lock file $lock_file\n" if
!unlink $lock_file;
print STDERR "Lock file has been removed.\n";
} else {
die "Lockfile present, another copy is punning
pid=$pid\n";
}
}
load_config();
my ($name, $passwd, $uid, $gid) =
getpwnam($runas_user) or die "$runas_user not in
passwd file";;
# Become daemon
#
my $pid;
if( !defined($pid = fork()) ) {
die "cannot fork: $!";
} elsif ($pid) {
# Create lockfile, and finish parent process
#
open(PID, "> $lock_file") || die "ast-rad-acc.pl:
Unable to create lockfile $lock_file\n";
print PID "$pid";
close PID;
chown $uid, $gid, $lock_file;
exit;
} else {
# daemon
setpgrp();
select(STDERR); $| = 1;
select(STDOUT); $| = 1;
openlog('ast-rad-acc', 'cons,pid', 'daemon');
syslog('notice', "RADIUS accounting for
Asterisk started");
}
# Install signall handler
#
$SIG{INT} = \&safe_exit;
$SIG{QUIT} = \&safe_exit;
$SIG{TERM} = \&safe_exit;
$SIG{HUP} = \&load_config;
# Drop privileges
#
setuid($uid);
$< = $uid;
$> = $uid;
my $astman = new Asterisk::Manager;
$astman->user($ast_username);
$astman->secret($ast_password);
$astman->host($ast_hostname);
my $ast_connected = 1;
while( 1 ) {
if( $astman->connect ) {
$ast_connected = 1;
syslog('info', 'Connected to Asterisk!');
$astman->setcallback('DEFAULT', \&status_callback);
eval { $astman->eventloop; };
} else {
syslog('err', 'Could not connect to Asterisk!') if
$ast_connected;
$ast_connected = 0;
}
sleep 1;
}
sub status_callback {
my (%event) = @_;
return unless defined(%event);
foreach (keys %event) {
syslog('debug', "$_: ". $event{$_} .
"\n" );
}
syslog('debug', "\n");
for ($event{'Event'}) {
# Variable read example
# print STDERR $astman->sendcommand(
Action => 'Getvar', Channel => $event{'Channel'},
Variable => 'DNID' );
$event{'Callerid'} = $1 if defined
$event{'Callerid'} && $event{'Callerid'} =~
/<(\d*)>/;
/newchannel/i && do {
my $call_origin = "originate";
$call_origin = "answer" if $event{'State'} =~
/^Ring$/i;
my $call_type = "VoIP";
$call_type = "Telephony" if
$event{'Channel'} =~
/^(Zap)|(VPB)|(phone)|(Modem)|(CAPI)|(mISDN)|(Console)/;
# session-protocol
# other, cisco, h323, multicast, sipv2, sdp,
frf11-trunk, cisco-switched, MarsAnalog, C1000Isdn,
aal2-trunk
my $protocol = 'other';
$protocol = 'sipv2' if $event{'Channel'} =~
/^SIP/i;
$protocol = 'h323' if $event{'Channel'} =~
/^h323/i;
$channels{$event{'Channel'}} = {
'CHANNEL' => $event{'Channel'},
'CALLERID' => $event{'Callerid'},
'DNID' => $event{'DNID'},
'UNIQUEID' => $event{'Uniqueid'},
'CALL_START' => time(),
'LINK_START' => time(),
'LINK_END' => time(),
'CALL_ORIGIN' => $call_origin,
'CALL_TYPE' => $call_type,
'CALL_PROTOCOL' => $protocol,
'CALL_ID' => $event{'Uniqueid'},
'RADIUS_Server' => $rad_serv,
'RADIUS_Secret' => $rad_sec,
'NAS_IP_Address' => $nas_ip
};
$channels{$event{'Channel'}}{'Remoteip'} =
$event{'Remoteip'} if defined $event{'Remoteip'};
};
/newexten/i && do {
$channels{$event{'Channel'}}{'DNID'} =
$event{'DNID'} if defined $event{'DNID'};
$channels{$event{'Channel'}}{'ACCOUNTCODE'} =
$event{'AppData'}
if defined $event{'Application'} &&
$event{'Application'} eq 'SetAccount';
if( defined
$event{'Application'} && $event{'Application'} eq
'SetVar') {
my ( $_var, $_val ) = split(/=/,
$event{'AppData'});
$channels{$event{'Channel'}}{$_var} = $_val;
}
};
/Newcallerid/i && do {
$channels{$event{'Channel'}}{'CALLERID'} =
$event{'Callerid'} if defined $event{'Callerid'};
};
/newstate/i && do {
$channels{$event{'Channel'}}{'CALLERID'} =
$event{'Callerid'} if defined $event{'Callerid'};
$channels{$event{'Channel'}}{'DNID'} =
$event{'DNID'} if defined $event{'DNID'};
};
/^link$/i && do {
my $channel = $event{'Channel1'};
return unless $channels{$channel};
$channels{$channel}{'DSTCHANNEL'} =
$event{'Channel2'};
$channels{$channel}{'LINK_START'} = time();
$channels{$event{'Channel2'}}{'LINK_START'} =
time();
$channels{$event{'Channel1'}}{'CALL_ID'} =
$event{'Uniqueid1'};
$channels{$event{'Channel2'}}{'CALL_ID'} =
$event{'Uniqueid1'};
$channels{$event{'Channel1'}}{'ACCOUNTCODE'} =
$channels{$event{'Channel1'}}{'CALLERID'}
if !defined
$channels{$event{'Channel1'}}{'ACCOUNTCODE'};
$channels{$event{'Channel2'}}{'ACCOUNTCODE'} =
$channels{$event{'Channel1'}}{'ACCOUNTCODE'};
syslog('info', 'Link without uniqueid') unless
$channels{$channel}{'UNIQUE'};
syslog('info', 'Link without channeld') unless
$channel;
syslog('info', 'Link on undefined channel') unless
$channels{$channel};
return unless($channel && $channels{$channel} &&
$channels{$channel}{'UNIQUEID'});
};
/^unlink$/i && do {
my $channel = $event{'Channel1'};
return unless $channels{$channel};
$channels{$event{'Channel1'}}{'LINK_END'} = time();
$channels{$event{'Channel2'}}{'LINK_END'} = time();
syslog('info', 'UnLink without uniqueid') unless
$channels{$channel}{'UNIQUE'};
syslog('info', 'UnLink without channeld') unless
$channel;
syslog('info', 'UnLink on undefined channel')
unless $channels{$channel};
return unless($channel && $channels{$channel} &&
$channels{$channel}{'UNIQUEID'});
};
/hangup/i && do {
my $channel = $event{'Channel'};
return unless $channels{$channel};
$channels{$event{'Channel'}}{'CALL_END'} = time();
$channels{$event{'Channel'}}{'CAUSE'} = 16;
$channels{$event{'Channel'}}{'CAUSE'} =
$event{'Cause'} if defined $event{'Cause'};
send_acc(%{$channels{$event{'Channel'}}});
delete $channels{$event{'Channel'}};
};
/shutdown/i && do {
die 'ast-rad-acc: Asterisk disconnect';
};
/Reload/i && do {
load_config();
};
}
}
sub send_acc {
my (%cdr) = @_;
my $r = new Authen::Radius(Host =>
$cdr{'RADIUS_Server'}, Secret =>
$cdr{'RADIUS_Secret'});
if( !defined $r ) {
syslog('crit', "RADIUS host '$cdr{'RADIUS_Server'}'
ERROR");
return;
}
$r->clear_attributes();
$r->add_attributes (
{ Name => 'NAS-IP-Address', Value =>
$cdr{'NAS_IP_Address'} },
{ Name => 'NAS-Port-Name', Value => $cdr{'CHANNEL'}
},
{ Name => 'User-Name', Value =>
$cdr{'ACCOUNTCODE'} },
{ Name => 'Calling-Station-Id', Value =>
$cdr{'CALLERID'} },
{ Name => 'Called-Station-Id', Value =>
$cdr{'DNID'} },
{ Name => 'Acct-Status-Type', Value => 'Stop'
},
{ Name => 'h323-call-type', Value =>
$cdr{'CALL_TYPE'} },
{ Name => 'h323-call-origin', Value =>
$cdr{'CALL_ORIGIN'} },
{ Name => 'h323-setup-time', Value =>
format_date($cdr{'CALL_START'}) },
{ Name => 'h323-connect-time', Value =>
format_date($cdr{'LINK_START'}) },
{ Name => 'h323-disconnect-time', Value =>
format_date($cdr{'LINK_END'}) },
{ Name => 'h323-disconnect-cause', Value =>
$cdr{'CAUSE'} },
{ Name => 'h323-voice-quality', Value => '0'
},
{ Name => 'Cisco-AVPair', Value =>
"session-protocol=$cdr{'CALL_PROTOCOL'}" },
{ Name => 'Cisco-AVPair', Value =>
"call-id=$cdr{'CALL_ID'}" },
{ Name => 'Acct-Session-Time', Value =>
$cdr{'LINK_END'} - $cdr{'LINK_START'} },
);
$r->add_attributes ( { Name => 'h323-remote-address',
Value => $cdr{'Remoteip'} } ) if defined
$cdr{'Remoteip'};
$r->send_packet (ACCOUNTING_REQUEST) and my $type =
$r->recv_packet;
syslog('crit', "No responce from RADIUS server") if
!defined $type;
}
#
# sample '09:16:05 GMT Sat Dec 11 2004'
#
sub format_date {
my ($date) = @_;
return strftime "%H:%M:%S GMT %a %b %e %Y",
gmtime($date);
}
# Signal Handlers
#
sub safe_exit {
my($sig) = @_;
syslog('crit', "Caught a SIG$sig - shutting down");
$astman->disconnect if $ast_connected;
unlink $lock_file or syslog('crit', "Unable to
create lockfile $lock_file\n");
closelog();
exit;
}
sub load_config {
my $conf=Config::IniFiles->new(-file =>
"$config_dir/extensions.conf");
syslog('crit', "Config file error!") if !defined
$conf;
$rad_serv = $conf->val('globals','RADIUS_Server');
$rad_sec = $conf->val('globals','RADIUS_Secret');
$nas_ip = $conf->val('globals','NAS_IP_Address');
syslog('notice', "extensions.conf loaded");
}
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
More information about the asterisk-users
mailing list