148 lines
4.4 KiB
148 lines
4.4 KiB
package NGCP::Panel::Utils::Interception;
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
use Data::Dumper;
|
|
use LWP::UserAgent;
|
|
use TryCatch;
|
|
use JSON;
|
|
|
|
sub request {
|
|
my ($c, $method, $uuid, $data) = @_;
|
|
|
|
my $a = _init($c);
|
|
return unless($a);
|
|
|
|
return unless($method eq 'POST' || $method eq 'PUT' || $method eq 'DELETE');
|
|
|
|
my @agents = @{ $a->{ua} };
|
|
my @urls = @{ $a->{url} };
|
|
for(my $i = 0; $i < scalar(@agents); ++$i) {
|
|
my $ua = $agents[$i];
|
|
my $url = $urls[$i];
|
|
if($method eq 'PUT' or $method eq 'DELETE') {
|
|
return unless($uuid);
|
|
$url .= '/'.$uuid;
|
|
}
|
|
$c->log->debug("performing $method for interception at $url");
|
|
try {
|
|
_request($c, $ua, $url, $method, $data);
|
|
} catch($e) {
|
|
# skip errors
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub _request {
|
|
my ($c, $ua, $url, $method, $data) = @_;
|
|
|
|
my $req = HTTP::Request->new($method => $url);
|
|
if($data) {
|
|
$req->content_type('application/json');
|
|
$req->content(encode_json($data));
|
|
}
|
|
my $res = $ua->request($req);
|
|
if($res->is_success) {
|
|
return 1;
|
|
} else {
|
|
$c->log->error("Failed to do $method on $url: " . $res->status_line);
|
|
return;
|
|
}
|
|
}
|
|
|
|
sub _init {
|
|
my ($c) = @_;
|
|
|
|
my @ua = ();
|
|
my @url = ();
|
|
my @cfgs = ();
|
|
if(ref $c->config->{intercept}->{agent} eq 'HASH') {
|
|
push @cfgs, $c->config->{intercept}->{agent};
|
|
} elsif(ref $c->config->{intercept}->{agent} eq 'ARRAY') {
|
|
@cfgs = @{ $c->config->{intercept}->{agent} };
|
|
}
|
|
unless(@cfgs) {
|
|
$c->log->error("No intercept agents configured in ngcp_panel.conf, rejecting request");
|
|
return;
|
|
}
|
|
foreach my $cfg(@cfgs) {
|
|
my $agent = LWP::UserAgent->new();
|
|
$agent->agent("Sipwise NGCP X1/0.2");
|
|
$agent->timeout(2);
|
|
if($cfg->{user} && $cfg->{pass}) {
|
|
$agent->credentials(
|
|
$cfg->{host}.":".$cfg->{port},
|
|
$cfg->{realm},
|
|
$cfg->{user},
|
|
$cfg->{pass}
|
|
);
|
|
}
|
|
push @ua, $agent;
|
|
push @url, $cfg->{schema}.'://'.$cfg->{host}.':'.$cfg->{port}.$cfg->{url};
|
|
}
|
|
return { ua => \@ua, url => \@url };
|
|
}
|
|
|
|
sub username_to_regexp_pattern {
|
|
|
|
my ($c,$voip_number,$username) = @_;
|
|
|
|
# $c is intended to use $c->config vars here.
|
|
# vsc.clir_code is not part of the panel conf, so
|
|
# the global conf would be required to load to get it.
|
|
# as this is not done elsewhere in panel code yet, we leave
|
|
# that as todo for now, and capture any vsc codes.
|
|
my $vsc_pattern = '(\*\d+\*)?';
|
|
#my $vsc_pattern = '(\*31\*)?';
|
|
|
|
my @pattern_elements = ();
|
|
# longest to shortest:
|
|
|
|
#1. the sip username itself:
|
|
push(@pattern_elements,$vsc_pattern . quotemeta($username));
|
|
#2. "international format": concat(concat('00',cc),ac,sn):
|
|
push(@pattern_elements,$vsc_pattern . '00' . $voip_number->cc . $voip_number->ac . $voip_number->sn);
|
|
#3. "e164 format": concat(cc,ac,sn):
|
|
push(@pattern_elements,$vsc_pattern . $voip_number->cc . $voip_number->ac . $voip_number->sn);
|
|
#4. "local format": concat(concat('0',ac),sn):
|
|
push(@pattern_elements,$vsc_pattern . '0' . $voip_number->ac . $voip_number->sn);
|
|
|
|
return '^(' . join('|',@pattern_elements) . ')$';
|
|
|
|
}
|
|
|
|
sub subresnum_from_number {
|
|
my ($c, $number, $err_code) = @_;
|
|
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
$err_code = sub { return 0; };
|
|
}
|
|
my $num_rs = $c->model('DB')->resultset('voip_numbers')->search(
|
|
\[ 'concat(cc,ac,sn) = ?', [ {} => $number ]]
|
|
)->search({
|
|
'subscriber_id' => { '!=' => undef },
|
|
},undef);
|
|
unless($num_rs->first) {
|
|
return 0 unless &{$err_code}("invalid number '" . $number . "'",'number',"Number does not exist");
|
|
}
|
|
my $sub = $num_rs->first->subscriber;
|
|
unless($sub) {
|
|
return 0 unless &{$err_code}("invalid number '" . $number . "', not assigned to any subscriber",'number',"Number is not active");
|
|
}
|
|
|
|
my $res = $num_rs->first->reseller;
|
|
unless($res) {
|
|
# with ossbss provisioning, reseller is not set on number,
|
|
# so take the long way here
|
|
$res = $sub->contract->contact->reseller;
|
|
unless($res) {
|
|
return 0 unless &{$err_code}("invalid number '" . $number . "', not assigned to any reseller",'number',"Number is not active");
|
|
}
|
|
}
|
|
|
|
return ($sub, $res, $num_rs->first);
|
|
}
|
|
|
|
1;
|