[Astpp-commit] SF.net SVN: astpp: [2184] trunk
Brought to you by:
darrenkw
From: <dar...@us...> - 2008-06-07 04:47:08
|
Revision: 2184 http://astpp.svn.sourceforge.net/astpp/?rev=2184&view=rev Author: darrenkw Date: 2008-06-06 21:47:11 -0700 (Fri, 06 Jun 2008) Log Message: ----------- Import Freeswitch support. This code works much, much faster using mod_perl. Modified Paths: -------------- trunk/astpp-common.pl trunk/astpp-ip-map.agi trunk/modules/ASTPP/lib/ASTPP.pm Added Paths: ----------- trunk/freeswitch/ trunk/freeswitch/README trunk/freeswitch/astpp-fs-xml.pl trunk/freeswitch/test-fs-xml.pl Modified: trunk/astpp-common.pl =================================================================== --- trunk/astpp-common.pl 2008-06-01 00:42:36 UTC (rev 2183) +++ trunk/astpp-common.pl 2008-06-07 04:47:11 UTC (rev 2184) @@ -1704,6 +1704,7 @@ my @pricelists = split ( m/,/m, $pricelist ); foreach my $pricelistname (@pricelists) { $pricelistname =~ s/"//g; #Strip off quotation marks + print STDERR "Pricelist: $pricelistname \n"; $record = &search_for_route($astpp_db,$config,$destination,$pricelist); print STDERR "pattern: $record->{pattern}\n" if $record->{pattern}; last if $record->{pattern}; #Returnes if we've found a match. @@ -1728,12 +1729,12 @@ } $record = &search_for_route($astpp_db,$config,$destination,$config->{default_brand}); print STDERR "pattern: $record->{pattern}\n" if $record->{pattern}; - } - if ( !$record->{pattern} ) { #If we have not found a route yet then we look in the "Default" pricelist. + } + if ( !$record->{pattern} ) { #If we have not found a route yet then we look in the "Default" pricelist. $record = &search_for_route($astpp_db,$config,$destination,$config->{default_brand}); print STDERR "pattern: $record->{pattern}\n" if $record->{pattern}; - } - print STDERR "Route: $record->{comment} Cost: $record->{cost} Pricelist: $record->{pricelist} Pattern: $record->{pattern}\n" if $record; + } + print STDERR "Route: $record->{comment} Cost: $record->{cost} Pricelist: $record->{pricelist} Pattern: $record->{pattern}\n" if $record; } elsif ($type =~ /ASTPP-DID/) { Modified: trunk/astpp-ip-map.agi =================================================================== --- trunk/astpp-ip-map.agi 2008-06-01 00:42:36 UTC (rev 2183) +++ trunk/astpp-ip-map.agi 2008-06-07 04:47:11 UTC (rev 2184) @@ -21,13 +21,17 @@ #exten => _X.,n,Goto(astpp-outgoing,${EXTEN},1) use DBI; +use ASTPP; use Asterisk::AGI; use POSIX qw(ceil floor); use POSIX qw(strftime); use strict; -use vars qw(@output $verbose $AGI $config $SIG $astpp_db); +use vars qw($ASTPP @output $verbose $AGI $config $SIG $astpp_db); @output = ( "STDERR", "LOGFILE" ); $verbose = 2; +$ASTPP = ASTPP->new; +$ASTPP->set_verbosity(4); #Tell ASTPP debugging how verbose we want to be. +$ASTPP->set_asterisk_agi($AGI); require "/usr/local/astpp/astpp-common.pl"; $AGI = new Asterisk::AGI; @@ -36,6 +40,7 @@ $config = &load_config(); $astpp_db = &connect_db( $config, @output ); $config = &load_config_db($astpp_db,$config); + $ASTPP->set_astpp_db($astpp_db); } sub ignore_hup { @@ -45,31 +50,12 @@ } } -sub get_ip() { - my ($number,$extension) = @_; - my ($sql,$tmp); - $tmp = "SELECT * FROM ip_map WHERE ip = " . $astpp_db->quote($number); - -##### I know I wrote it with the OR statement for some reason but I can't figure out why. I'm leaving it here for now. -# $tmp = "SELECT * FROM ip_map WHERE ip = " . $astpp_db->quote($number) -# . " AND prefix IS NULL OR $extension RLIKE prefix ORDER BY LENGTH(prefix) DESC LIMIT 1"; -########### -$tmp = "SELECT * FROM ip_map WHERE ip = " . $astpp_db->quote($number) - . " AND prefix IN (NULL,'') OR ip = " . $astpp_db->quote($number) . " AND " . $astpp_db->quote($extension) . " RLIKE prefix ORDER BY LENGTH(prefix) DESC LIMIT 1"; - print STDERR $tmp if $config->{debug} == 1; - $AGI->verbose( "$tmp\n", $verbose ) if $config->{debug} == 1; - $sql = - $astpp_db->prepare($tmp); - $sql->execute; - my $anidata = $sql->fetchrow_hashref; - $sql->finish; - return $anidata; -} ################# Program Starts Here ################################# my ($ip, $extension) = @ARGV; my ($sql); &initialize; -my $anidata = &get_ip($ip,$extension); +my $anidata = $ASTPP->ip_address_authenticate( ip_address => $ip, destination => $extension); + if ($anidata) { my $carddata=&get_account($astpp_db, $anidata->{account}); $AGI->set_variable( 'ACCOUNTCODE', "\"$carddata->{cc}\"" ); Added: trunk/freeswitch/README =================================================================== --- trunk/freeswitch/README (rev 0) +++ trunk/freeswitch/README 2008-06-07 04:47:11 UTC (rev 2184) @@ -0,0 +1 @@ +This directory contains the support for Freeswitch. Please be aware that this is a work under development. Added: trunk/freeswitch/astpp-fs-xml.pl =================================================================== --- trunk/freeswitch/astpp-fs-xml.pl (rev 0) +++ trunk/freeswitch/astpp-fs-xml.pl 2008-06-07 04:47:11 UTC (rev 2184) @@ -0,0 +1,177 @@ +#!/usr/bin/perl +# +# ASTPP - Open Source Voip Billing +# +# Copyright (C) 2008, Aleph Communications +# +# Darren Wiebe (da...@al...) +# +# This program is Free Software and is distributed under the +# terms of the GNU General Public License version 2. +############################################################ +# +# Usage-example: +# + +use DBI; +use CGI; +use CGI qw/:standard Vars/; +use ASTPP; +use strict; +use vars qw($params $ASTPP @output $config $astpp_db $verbosity ); +use Locale::gettext_pp qw(:locale_h); +require "/usr/local/astpp/astpp-common.pl"; +$ENV{LANGUAGE} = "en"; # de, es, br - whatever +print STDERR "Interface language is set to: " . $ENV{LANGUAGE} . "\n"; +bindtextdomain( "astpp", "/usr/local/share/locale" ); +textdomain("astpp"); +$verbosity = 2; +@output = ("STDERR"); +$ASTPP = ASTPP->new; +$ASTPP->set_verbosity(4); #Tell ASTPP debugging how verbose we want to be. + + +sub initialize() { + $config = &load_config(); + $astpp_db = &connect_db( $config, @output ); + $ASTPP->set_astpp_db($astpp_db); + $config = &load_config_db( $astpp_db, $config ) if $astpp_db; +} + +################# Programs start here ####################################### +&initialize; +my ( $xml, $maxlength, $maxmins,$callstatus ); +foreach my $param ( param() ) { + $params->{$param} = param($param); + $ASTPP->debug( debug => "$param $params->{$param}" ); +} +$xml = header(-type => 'text/plain'); + +$ASTPP->debug( debug => "Destination = $params->{'Caller-Destination-Number'}"); + +if ($params->{section} eq "dialplan") { +$xml = $ASTPP->fs_dialplan_xml_header( xml => $xml, destination_number => $params->{'Caller-Destination-Number'}); + +if (!$params->{variable_accountcode}) { +# First we strip off X digits to see if this account is prepending numbers +# as authentications + $ASTPP->debug( debug => "Checking CC Number: " . $params->{'Caller-Destination-Number'}); + my $cc = substr( $params->{'Caller-Destination-Number'}, 0, $config->{cardlength} ); + my $sql = $astpp_db->prepare("SELECT number FROM accounts WHERE cc = $cc"); + $sql->execute; + my $record = $sql->fetchrow_hashref; + $sql->finish; + $params->{variable_accountcode} = $record->{cardnum} if ($record->{cardnum}); +} +if (!$params->{variable_accountcode}) { + $ASTPP->debug( debug => "Checking IP Address:" . $params->{network_addr}); + my $ip_data = $ASTPP->ip_address_authenticate( ip_address => $params->{network_addr}, destination => $params->{'Caller-Destination-Number'}); + if ($ip_data) { + $params->{variable_accountcode} = $ip_data->{account}; + $params->{'Caller-Destination-Number'} =~ s/$ip_data->{prefix}//g; + } +} + +$ASTPP->debug( debug => "$params->{variable_accountcode}, $params->{'Caller-Destination-Number'}"); + +my $carddata = &get_account( $astpp_db, $params->{variable_accountcode} ); # Fetch all the account info from the db. + +if ( !$carddata->{number} ) { # Check to see if the account exists. If not then exit. + $ASTPP->debug( debug => "CALLSTATUS 2"); + $ASTPP->debug( debug =>"CANNOT RETRIEVE CARD"); + $xml .= "<action application=\"reject\" data=\"CANNOT RETRIEVE ACCOUNT\"/>\n"; + $xml = $ASTPP->fs_dialplan_xml_footer( xml => $xml); + print $xml; + exit(0); +} + +if ($carddata->{dialed_modify}) { + my @regexs = split(m/,/m, $carddata->{dialed_modify}); + foreach my $regex (@regexs) { + $regex =~ s/"//g; #Strip off quotation marks + my ($grab,$replace) = split(m!/!i, $regex); # This will split the variable into a "grab" and "replace" as needed + $ASTPP->debug( debug => "Grab: $grab"); + $ASTPP->debug( debug => "Replacement: $replace"); + $ASTPP->debug( debug => "Phone Before: $params->{'Caller-Destination-Number'}"); + $$params->{'Caller-Destination-Number'} =~ s/$grab/$replace/is; + $ASTPP->debug( debug => "Phone After: $params->{'Caller-Destination-Number'}" ); + } + } + +$ASTPP->debug( debug => "FINDING LIMIT FOR: " . $carddata->{number}); +($callstatus, $maxlength) = &max_length($astpp_db, $config, $carddata, $params->{'Caller-Destination-Number'}); +my $routeinfo = &get_route( $astpp_db, $config, $params->{'Caller-Destination-Number'}, $carddata->{pricelist},$carddata ); + +$ASTPP->debug( debug => "Minimum Charge on call = " . $routeinfo->{cost}); +my $minimumcharge = $routeinfo->{cost}; +my @reseller_list; +$ASTPP->debug( debug => "CALLSTATUS: $callstatus MAX_LENGTH: $maxlength"); +while ( $carddata->{reseller} && $maxlength > 1 && $callstatus == 1) { + $ASTPP->debug( debug => "FINDING LIMIT FOR: $carddata->{reseller}"); + $carddata = &get_account( $astpp_db, $carddata->{reseller} ); + push @reseller_list, $carddata->{number}; + $ASTPP->debug( debug => "ADDING $carddata->{number} to the list of resellers for this account"); + my ($resellercallstatus, $resellermaxlength) = &max_length($astpp_db, $config, $carddata, $params->{'Caller-Destination-Number'}); + my $routeinfo = &get_route( $astpp_db, $config, $params->{'Caller-Destination-Number'}, $carddata->{pricelist},$carddata ); + if ($resellercallstatus != 1) { + $carddata->{reseller} = ""; + $callstatus = $resellercallstatus; + } elsif ($resellermaxlength < $maxlength) { + $maxlength = $resellermaxlength; + } + $ASTPP->debug( debug => "Reseller cost = $routeinfo->{cost} and minimum charge is $minimumcharge"); + if ($resellermaxlength < 1 || $routeinfo->{cost} > $minimumcharge ) { + $ASTPP->debug( debug => "Reseller call is priced too cheap! Call being barred!"); + $xml .= "<action application=\"reject\" data=\"Reseller call is priced too cheap! Call being barred!\"/>\n"; + $xml = $ASTPP->fs_dialplan_xml_footer( xml => $xml); + print $xml; + exit(0); + } + $ASTPP->debug( debug => "RESELLER Max Length: $resellermaxlength"); + $ASTPP->debug( debug => "RESELLER Call Status: $resellercallstatus"); +} + +if ($config->{debug} == 1) { + $ASTPP->debug( debug => "PRINTING LIST OF RESELLERS FOR THIS ACCOUNT" ); + foreach my $reseller (@reseller_list) { + $ASTPP->debugb( debug => "RESELLER: $reseller" ); + } +} + +$ASTPP->debug( "Max Call Length: $maxlength minutes" ); +$ASTPP->debug( "Call Status: $callstatus" ); + +if ( $maxlength <= 1 ) { + $ASTPP->debug( debug => "NOT ENOUGH CREDIT" ); + $xml .= "<action application=\"reject\" data=\"NOT ENOUGH CREDIT\"/>\n"; + $xml = $ASTPP->fs_dialplan_xml_footer( xml => $xml); + print $xml; + exit(0); +} + +# Set the timelimit as well as other variables which are needed in the dialplan. +my $timelimit = "L(" . sprintf( "%.0f", $maxlength * 60 * 1000 ) . ":60000:30000)"; + +$ASTPP->debug( debug => "Looking for outbound Route" ); +my $routeinfo = &get_route($astpp_db,$config,$params->{'Caller-Destination-Number'},$carddata->{pricelist},$carddata); +# Get the list of routes for the phone number. +my @outboundroutes = &get_outbound_routes( $astpp_db, $params->{'Caller-Destination-Number'},$carddata,$routeinfo, @reseller_list ); +foreach my $route (@outboundroutes) { + $ASTPP->debug( debug => "$route->{trunk}: cost $route->{cost}\t $route->{pattern}" ); + if ($route->{cost} > $routeinfo->{cost}) { + $ASTPP->debug( debug => "$route->{trunk}: $route->{cost} > $routeinfo->{cost}, skipping" ); + } else { + $xml .= $ASTPP->fs_dialplan_xml_bridge( destination_number => $params->{'Caller-Destination-Number'}, + route_prepend => $route->{prepend}, + trunk_name => $route->{trunk}); + } +} +$xml = $ASTPP->fs_dialplan_xml_footer( xml => $xml); +} elsif ($params->{section} eq "directory") { + $xml = $ASTPP->fs_directory_xml_header( xml => $xml); + $xml = $ASTPP->fs_directory_xml( xml => $xml); + $xml = $ASTPP->fs_directory_xml_footer( xml => $xml); +} +$ASTPP->debug( debug => $xml); +print $xml; +exit(0); Property changes on: trunk/freeswitch/astpp-fs-xml.pl ___________________________________________________________________ Name: svn:executable + * Added: trunk/freeswitch/test-fs-xml.pl =================================================================== --- trunk/freeswitch/test-fs-xml.pl (rev 0) +++ trunk/freeswitch/test-fs-xml.pl 2008-06-07 04:47:11 UTC (rev 2184) @@ -0,0 +1,45 @@ +#!/usr/bin/perl +# +# ASTPP - Open Source Voip Billing +# +# Copyright (C) 2008, Aleph Communications +# +# Darren Wiebe (da...@al...) +# +# This program is Free Software and is distributed under the +# terms of the GNU General Public License version 2. +############################################################ + +use Time::HiRes qw( gettimeofday tv_interval ); +#use HTTP::Request; +#use LWP::UserAgent; +#use URI::URL; +#use WWW::Curl; +use LWP::Simple; + + +my $starttime = [gettimeofday]; + +my $url = 'http://localhost/cgi-bin/astpp-fs-xml.pl?section=dialplan&Caller-Destination-Number=123456789&variable_accountcode=1000'; +my $url = 'http://localhost/perl/astpp-fs-xml.pl?section=dialplan&Caller-Destination-Number=123456789&variable_accountcode=1000'; + +#my $req = HTTP::Request->new(POST, $url, $headers); +#my $ua = LWP::UserAgent->new(); +#my $resp = $ua->request($req); +#if ($resp->is_success) { +# +# print $resp->content; +#} else { +# print $resp->message; +#} + +my $count = 0; +while ($count < 500) { +print $count; +$count++; +my $content = get $url; +} +print $content; + +my $generation_time = tv_interval($starttime); +print "\n\n" . $generation_time . "\n\n"; Property changes on: trunk/freeswitch/test-fs-xml.pl ___________________________________________________________________ Name: svn:executable + * Modified: trunk/modules/ASTPP/lib/ASTPP.pm =================================================================== --- trunk/modules/ASTPP/lib/ASTPP.pm 2008-06-01 00:42:36 UTC (rev 2183) +++ trunk/modules/ASTPP/lib/ASTPP.pm 2008-06-07 04:47:11 UTC (rev 2184) @@ -76,6 +76,140 @@ # $self->{_config} = %config_hash if %config_hash; #} +sub ip_address_authenticate #Authenticates call by caller ip address. Works with both Asterisk(tm) and Freeswitch(tm) +# Requires +# ip_address = IP Address of calling device +# destination = Dialed number +{ + my ($self, %arg) = @_; + my ($sql,$tmp); + $tmp = "SELECT * FROM ip_map WHERE ip = " . $self->{_astpp_db}->quote($arg{ip_address}) + . " AND prefix IN (NULL,'') OR ip = " . $self->{_astpp_db}->quote($arg{ip_address}) + . " AND " . $self->{_astpp_db}->quote($arg{destination}) . " RLIKE prefix ORDER BY LENGTH(prefix) DESC LIMIT 1"; + $sql = $self->{_astpp_db}->prepare($tmp); + $sql->execute; + my $anidata = $sql->fetchrow_hashref; + $sql->finish; + return $anidata; +} + +sub fs_dialplan_xml_header +#Return the opening lines of the Freeswitch(TM) xml dialplan +{ + my ($self, %arg) = @_; + $arg{xml} .= "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"; + $arg{xml} .= "<document type=\"freeswitch/xml\">\n"; + $arg{xml} .= "<section name=\"dialplan\" description=\"ASTPP Dynamic Routing\">\n"; + $arg{xml} .= "<context name=\"default\">\n"; + $arg{xml} .= "<extension name=\"$arg{destination_number}\">\n"; + $arg{xml} .= "<condition field=\"destination_number\" expression=\"$arg{destination_number}\">\n"; + return $arg{xml}; +} + +sub fs_dialplan_xml_bridge +#Return the bridge command along with details. This is only called if a call is approved. +# Requires the following variables: +# destination_number = The number we are trying to call +# trunk_name = The name of the trunk we're using. +# route_prepend = What do we tag on for numbers on this route? +{ + my ($self, %arg) = @_; + my ( $sql, $trunkdata, $dialstring ); + $sql = $self->{_astpp_db}->prepare( "SELECT * FROM trunks WHERE name = " + . $self->{_astpp_db}->quote( $arg{trunk_name} ) ); + $sql->execute; + $trunkdata = $sql->fetchrow_hashref; + $arg{route_prepend} = "" if !$arg{route_prepend}; + $sql->finish; + if ($trunkdata->{dialed_modify} && $trunkdata->{dialed_modify} ne "") { + my @regexs = split(m/","/m, $trunkdata->{dialed_modify}); + foreach my $regex (@regexs) { + $regex =~ s/"//g; #Strip off quotation marks + my ($grab,$replace) = split(m!/!i, $regex); # This will split the variable into a "grab" and "replace" as needed + print STDERR "Grab: $grab\n"; + print STDERR "Replacement: $replace\n"; + print STDERR "Phone Before: $arg{destination_number}\n"; + $arg{destination_number} =~ s/$grab/$replace/is; + print STDERR "Phone After: $arg{destination_number}\n"; + } + } + if ( $trunkdata->{tech} eq "Zap" ) { + $dialstring = "<action application=\"bridge\" data=\"openzap/" . $trunkdata->{path} . "/1/" . $arg{route_prepend} . $arg{destination_number}. "\"/>\n"; + return $dialstring; + } + elsif ( $trunkdata->{tech} eq "SIP" ) { + my ($profile,$dest) = split(m/","/m, $trunkdata->{path}); + $profile =~ s/"//g; #Strip off quotation marks + $dest =~ s/"//g; #Strip off quotation marks + if ($profile eq "gateway") { + $dialstring = "<action application=\"bridge\" data=\"sofia/gateway/" . $dest . "/" . $arg{route_prepend} . $arg{destination_number} . "\"/>\n"; + } else { + $dialstring = "<action application=\"bridge\" data=\"sofia/" . $profile . "/" . $arg{route_prepend} . $arg{destination_number} . "\@" . $dest . "\"/>\n"; + } + return $dialstring; + } + else { + print STDERR "CANNOT ROUTE THIS CALL!!!!!\n"; + return ""; + } +} + +sub fs_dialplan_xml_footer +#Return the closing lines of the Freeswitch(TM) xml dialplan +{ + my ($self, %arg) = @_; + $arg{xml} .= "</condition>\n"; + $arg{xml} .= "</extension>\n"; + $arg{xml} .= "</context>\n"; + $arg{xml} .= "</section>\n"; + $arg{xml} .= "</document>\n"; + return $arg{xml}; +} + +sub fs_directory_xml_header +#Return the opening lines of the Freeswitch(TM) xml directory +#xml = Current XML code, usually blank. +#domain = domain name +{ + my ($self, %arg) = @_; + $arg{xml} .= "<?xml version=\"1.0\"?>\n"; + $arg{xml} .= "<document type=\"freeswitch/xml\">\n"; + $arg{xml} .= "<section name=\"directory\" description=\"User Directory\">\n"; + $arg{xml} .= "<domain name=\"" . $arg{domain} . "\">\n"; + return $arg{xml}; +} + +sub fs_directory_xml +#Return the user detail lines for Freeswitch(TM) sip athentication. +#xml = Current XML code +{ + my ($self, %arg) = @_; + my ($sql); + $sql = $self->{_astpp_db}->prepare("SELECT * FROM fs_users"); + $sql->execute; + while (my $record = $sql->fetchrow_hashref) { + $arg{xml} .= "<user id=\"" . $record->{user} . "\">\n"; + $arg{xml} .= "<params>\n"; + $arg{xml} .= "<param name=\"password\" value=\"" . $record->{password} . "\"/>\n"; + $arg{xml} .= "</params>\n"; + $arg{xml} .= "</user>\n"; + }; + return $arg{xml}; +} + + + +sub fs_directory_xml_footer +#Return the closing lines of the Freeswitch(TM) xml dialplan +#xml = Current XML code +{ + my ($self, %arg) = @_; + $arg{xml} .= "</domain>\n"; + $arg{xml} .= "</section>\n"; + $arg{xml} .= "</document>\n"; + return $arg{xml}; +} + sub debug #Prints debugging if appropriate # { @@ -208,7 +342,6 @@ =head1 SYNOPSIS use ASTPP; - blah blah blah =head1 DESCRIPTION This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |