[Astpp-commit] SF.net SVN: astpp:[2288] trunk/freeswitch/ASTPP.pm
Brought to you by:
darrenkw
From: <dar...@us...> - 2009-10-09 14:59:52
|
Revision: 2288 http://astpp.svn.sourceforge.net/astpp/?rev=2288&view=rev Author: darrenkw Date: 2009-10-09 14:59:42 +0000 (Fri, 09 Oct 2009) Log Message: ----------- This file can be run as an apache module. Added Paths: ----------- trunk/freeswitch/ASTPP.pm Added: trunk/freeswitch/ASTPP.pm =================================================================== --- trunk/freeswitch/ASTPP.pm (rev 0) +++ trunk/freeswitch/ASTPP.pm 2009-10-09 14:59:42 UTC (rev 2288) @@ -0,0 +1,559 @@ +package ModPerl::ASTPP; + +# +# 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 Apache2::Const qw(:common); +use Apache2::Request; +use Apache::DBI; +use DBI; +use CGI; +use CGI qw/:standard Vars/; +use ASTPP; +use XML::Simple; +use Data::Dumper; +use URI::Escape; +use Time::HiRes qw( gettimeofday tv_interval ); + +use POSIX; +use POSIX qw(strftime); + +use strict; +$Apache::DBI::DEBUG = 2; + +use vars + qw( $cdr_db $ASTPP @output $config $freeswitch_db $astpp_db $verbosity ); +use Locale::gettext_pp qw(:locale_h); +my $starttime = [gettimeofday]; +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; + $freeswitch_db = &connect_freeswitch_db( $config, @output ); + $ASTPP->set_freeswitch_db($freeswitch_db); + $cdr_db = &cdr_connect_db( $config, @output ); + $config->{cdr_table} = $config->{freeswitch_cdr_table}; +} + +################# Programs start here ####################################### +&initialize; + +sub handler { + my $r = shift; +my ( $ipinfo, $params,$xml, $maxlength, $maxmins, $callstatus,$astppdid,$didinfo ); +my $starttime = [gettimeofday]; +my $q = new CGI; + + +foreach my $param ( $q->param() ) { + $params->{$param} = $q->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" ) { + # Check to see if this is a DID. If it is we handle it differently. + # + $didinfo = &get_did($astpp_db, $params->{'Caller-Destination-Number'}); + if ($didinfo->{number}) { + $astppdid = "ASTPP-DID"; + $ASTPP->debug( debug => "This is a call for a DID: "); + $params->{variable_accountcode} = $didinfo->{account}; + } + + + 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->{'Hunt-Network-Addr'} ); + $ipinfo = $ASTPP->ip_address_authenticate( + ip_address => $params->{'Hunt-Network-Addr'}, + destination => $params->{'Caller-Destination-Number'} + ); + if ($ipinfo->{account} ne "") { + $params->{variable_accountcode} = $ipinfo->{account}; + $params->{'Caller-Destination-Number'} =~ s/$ipinfo->{prefix}//g; + } + } +print STDERR "IP ACCOUNT: $ipinfo->{account} \n"; + + $xml = $ASTPP->fs_dialplan_xml_header( + xml => $xml, + destination_number => $params->{'Caller-Destination-Number'}, + DID => $didinfo->{number}, + IP => 123 #$ipinfo->{account} + ); + + $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; + $ASTPP->debug( debug => "Returning nothing so dialplan can continue." ); + $r->print(""); + +my $generation_time = tv_interval($starttime); +print STDERR "TOOK: " . $generation_time ; + + exit(1); +# return OK; + } + + 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,$astppdid + ); + + $ASTPP->debug( debug => "Cost: " . $routeinfo->{cost} ); + $ASTPP->debug( debug => "Pricelist: " . $routeinfo->{pricelist} ); + my $minimumcharge = $routeinfo->{cost}; + my @reseller_list; + $ASTPP->debug( debug => "CALLSTATUS: $callstatus MAX_LENGTH: $maxlength" ); + + if (!$routeinfo->{cost} && !$routeinfo->{pricelist}) { + $ASTPP->debug( debug => "COULD NOT FIND ROUTE. EXITING SO DIALPLAN CAN TAKE OVER" ); +my $generation_time = tv_interval($starttime); +print STDERR "TOOK: " . $generation_time ; + $r->print($xml); + exit(1); +# return OK; + } + 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 ); + $r->print( $xml); +my $generation_time = tv_interval($starttime); +print STDERR "TOOK: " . $generation_time ; + exit(1); + } + $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 ); + $r->print( $xml); +my $generation_time = tv_interval($starttime); +print STDERR "TOOK: " . $generation_time ; + exit(1); + } elsif ($config->{call_max_length} && $maxlength < $config->{call_max_length} / 1000){ + $maxlength = $config->{call_max_length} / 1000; + } + + $xml = $ASTPP->fs_dialplan_xml_timelimit( + xml => $xml, + max_length => $maxlength, + accountcode => $carddata->{number} + ); + +# 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" ); + $routeinfo = &get_route( + $astpp_db, $config, + $params->{'Caller-Destination-Number'}, + $carddata->{pricelist}, $carddata, $astppdid + ); + + if ($didinfo->{number} ) { + $ASTPP->debug( debug => "THIS IS A DID CALL: $xml"); + my ($returned_data) = $ASTPP->fs_dialplan_xml_did( + did => $params->{'Caller-Destination-Number'} + ); + $xml .= $returned_data; + } else { + # 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 { + my ($returned_data,$junk) = $ASTPP->fs_dialplan_xml_bridge( + destination_number => $params->{'Caller-Destination-Number'}, + route_prepend => $route->{prepend}, + trunk_name => $route->{trunk}, + route_id => $route->{id} + ); + $xml .= $returned_data; + } + } + } + $xml = $ASTPP->fs_dialplan_xml_footer( xml => $xml ); + $ASTPP->debug( debug => $xml ); + print $xml; + exit(1); +} +if ( $params->{section} eq "directory" ) { + + #hostname darren-laptop + #section directory + #tag_name domain + #key_name name + #key_value 192.168.2.119 + #action sip_auth + #sip_profile internal + #sip_user_agent Zoiper rev.1118 + #sip_auth_username 1000 + #sip_auth_realm 192.168.2.119 + #sip_auth_nonce 83005e62-7e13-11dd-9eb1-25560b0691a8 + #sip_auth_uri sip:192.168.2.119;transport=UDP + #sip_auth_qop auth + #sip_auth_cnonce a79169d2656f292a + #sip_auth_nc 00000001 + #sip_auth_response 4475154556879ec2017978f1347192a6 + #sip_auth_method REGISTER + #key id + #user 1000 + #domain 192.168.2.119 + #ip 192.168.2.119 + + if ($params->{'user'}) { + $xml = $ASTPP->fs_directory_xml_header( xml => $xml ); + $xml = $ASTPP->fs_directory_xml( + xml => $xml, + ip => $params->{'ip'}, + user => $params->{'user'}, + domain => $params->{'domain'} + ); + $xml = $ASTPP->fs_directory_xml_footer( xml => $xml ); + } + $ASTPP->debug( debug => $xml ); + $r->print ($xml); + exit(1); +} +if ( $params->{cdr} ) { + +$r->print(header( -type => 'text/plain' )); + +# create object +my $xml = new XML::Simple; + +# read XML file +my $data = $xml->XMLin($params->{cdr}); + +# print output +#print STDERR Dumper($data); + + +my $tmp = "INSERT INTO " . $config->{freeswitch_cdr_table} . "(accountcode,src,dst,dcontext,clid,channel,dstchannel,lastapp," + . "lastdata,calldate,answerdate,enddate,duration,billsec,disposition,amaflags,uniqueid,userfield,read_codec," + . "write_codec,cost,vendor,provider,trunk,outbound_route,progressmsec,answermsec,progress_mediamsec) VALUES (" + . "'" + . $data->{variables}->{accountcode} + . "'" + . "," + . "'" + . $data->{callflow}->{caller_profile}->{username} + . "'" + . "," +# . $cdr_db->quote($data->{callflow}->{caller_profile}->{originatee}->{originatee_caller_profile}->{destination_number}) + . "'" + . $data->{callflow}->{caller_profile}->{destination_number} + . "'" + . "," +# . $cdr_db->quote($data->{callflow}->{caller_profile}->{originatee}->{originatee_caller_profile}->{context}) + . "'" + . $data->{callflow}->{caller_profile}->{context} + . "'" + . "," + . "'" + . uri_unescape($data->{variables}->{caller_id}) + . "'" +# . "\"" . $cdr_db->quote($data->{callflow}->{caller_profile}->{originatee}->{originatee_caller_profile}->{caller_id_name}) . "\"" +# . "<" . $cdr_db->quote($data->{callflow}->{caller_profile}->{originatee}->{originatee_caller_profile}->{caller_id_number}) . ">" +# . "\"" . $data->{callflow}->{caller_profile}->{caller_id_name} . "\"" +# . "<" . $data->{callflow}->{caller_profile}->{caller_id_number} . ">" + . "," + . "'" + . uri_unescape($data->{variables}->{channel_name}) + . "'" + . "," + . "''" + . "," + . "'" . $data->{variables}->{last_app} . "'" + . "," + . "'" . uri_unescape($data->{variables}->{last_arg}) . "'" + . "," + . "'" + . uri_unescape($data->{variables}->{start_stamp}) + . "'" + . "," + . "'" . uri_unescape($data->{variables}->{answer_stamp}) . "'" + . "," + . "'" + . uri_unescape($data->{variables}->{end_stamp}) + . "'" + . "," + . "'" + . $data->{variables}->{duration} + . "'" + . "," + . "'" + . $data->{variables}->{billsec} + . "'" + . "," + . "'" + . $data->{variables}->{hangup_cause} + . "'" + . "," + . "''" + . "," + . "'" + . $data->{callflow}->{caller_profile}->{uuid} + . "'" + . "," + . "''" + . "," + . "'" . $data->{variables}->{read_code} . "'" + . "," + . "'" . $data->{variables}->{write_code} . "'" + . ",'none','none'" + . "," + . "'" . $data->{variables}->{provider} . "'" + . "," + . "'" . $data->{variables}->{trunk} . "'" + . "," + . "'" . $data->{variables}->{outbound_route} . "'" + . "," + . "'" . $data->{variables}->{progressmsec} . "'" + . "," + . "'" . $data->{variables}->{answermsec} . "'" + . "," + . "'" . $data->{variables}->{progress_mediamsec} . "'" + . ")"; + +print STDERR "\n" . $tmp . "\n"; +$cdr_db->do($tmp); +$r->print( "Wrote CDR"); +my (@chargelist); +push @chargelist, $data->{callflow}->{caller_profile}->{uuid}; +&processlist( $astpp_db, $cdr_db, $config, \@chargelist ); +print STDERR "VENDOR CHARGES: " . $config->{trackvendorcharges} . "\n"; +if ($config->{trackvendorcharges} == 1 && $data->{variables}->{accountcode}) { + &vendor_process_rating_fs( $astpp_db, $cdr_db, $config, "none", $data->{callflow}->{caller_profile}->{uuid},""); +} + +&process_callingcard_cdr if $data->{variables}->{callingcard}; + +sub process_callingcard_cdr() { + my ( $cardinfo, $brandinfo, $numberinfo, $pricelistinfo,$cc ); + my $destination = $data->{callflow}->{caller_profile}->{destination_number}; + $destination =~ s/@.*//g; + my $cardnumber = $data->{variables}->{callingcard}; + $cardinfo = &get_callingcard( $astpp_db, $cardnumber, $config ); + if ( !$cardinfo ) { + $cardinfo = &get_account_cc( $astpp_db, $cardnumber ); + $cc = 1 if $cardinfo; + } + $brandinfo = &get_cc_brand( $astpp_db, $cardinfo->{brand} ) if $cc == 0; + if ($brandinfo->{reseller}) { + $config = &load_config_db_reseller($astpp_db,$config,$brandinfo->{reseller}); + } + $config = &load_config_db_brand($astpp_db,$config,$cardinfo->{brand}); + $pricelistinfo = &get_pricelist( $astpp_db, $brandinfo->{pricelist} ) + if $cc == 0; + $pricelistinfo = &get_pricelist( $astpp_db, $cardinfo->{pricelist} ) + if $cc == 1; + + print STDERR "THIS IS A CALLINGCARD CALL! \n"; + print STDERR "CARD: $cardinfo->{cardnumber} \n"; + print STDERR "CARD: $cardnumber \n"; + $numberinfo = &get_route( + $astpp_db, $config, + $destination, + $brandinfo->{pricelist}, $cardinfo + ); + if ( $data->{variables}->{billsec} > 0 ) + { + $ASTPP->debug( + debug => "CALL ANSWERED", + verbosity => $verbosity + ); + my $increment; + if ( $numberinfo->{inc} > 0 ) { + $increment = $numberinfo->{inc}; + } + else { + $increment = $pricelistinfo->{inc}; + } + $ASTPP->debug( + debug => +"$numberinfo->{connectcost}, $numberinfo->{cost}, $data->{variables}->{billsec}, $increment, $numberinfo->{includedseconds}", + verbosity => $verbosity + ); + my $charge = &calc_call_cost( + $numberinfo->{connectcost}, + $numberinfo->{cost}, + $data->{variables}->{billsec}, + $increment, + $numberinfo->{includedseconds} + ); + $ASTPP->debug( + debug => "Cost $charge ", + verbosity => $verbosity + ); + if ( $cardinfo->{minute_fee_pennies} > 0 ) { + $charge = + ( ( $cardinfo->{minute_fee_pennies} * 100 ) + + $charge ) + if $cardinfo->{timeused} + + $data->{variables}->{billsec} => + $cardinfo->{minute_fee_minutes}; + } + if ( $cardinfo->{min_length_pennies} > 0 + && ( $cardinfo->{min_length_minutes} * 60 ) > + $data->{variables}->{billsec} ) + { + $charge = + ( ( $cardinfo->{min_length_pennies} * 100 ) + + $charge ); + } + print STDERR "CARDNUMBER: " . $cardinfo->{cardnumber}; + &write_callingcard_cdr( + $astpp_db, + $config, + $cardinfo, + uri_unescape($data->{variables}->{caller_id}), + $destination, + uri_unescape($data->{variables}->{hangup_cause}), + uri_unescape($data->{variables}->{start_stamp}), + $charge, + $data->{variables}->{billsec} + ); + &callingcard_set_in_use($astpp_db,$cardinfo,0); + &callingcard_update_balance($astpp_db,$cardinfo,$charge); + } + } + + +} + +my $generation_time = tv_interval($starttime); +print STDERR "TOOK: " . $generation_time ; +} +my $generation_time = tv_interval($starttime); +print STDERR "TOOK: " . $generation_time ; +1; Property changes on: trunk/freeswitch/ASTPP.pm ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |