TT#2371 Implement 3pcc for sms

If pcc is enabled for a subscriber, don't forward sms immediately,
rather than mark for forwarding and let the API forward it on
incoming request.

Change-Id: I75104266a1c1fccc7165af9ba65b31f085d7081f
changes/01/10701/2
Andreas Granig 9 years ago
parent 1bbad6aaf2
commit 5ca51f930a

@ -14,6 +14,7 @@ use Path::Tiny qw(path);
use Safe::Isa qw($_isa);
use NGCP::Panel::Utils::Sems;
use NGCP::Panel::Utils::SMS;
require Catalyst::ActionRole::ACL;
require Catalyst::ActionRole::CheckTrailingSlash;
@ -25,7 +26,7 @@ sub allowed_methods{
}
sub api_description {
return 'Allows to place calls via the API.';
return 'Allows to control queued calls and sms via the API.';
};
sub query_params {
@ -42,7 +43,7 @@ sub dispatch_path{
return '/api/partycallcontrols/';
}
sub relation{
return 'http://purl.org/sipwise/ngcp-api/#rel-callcontrols';
return 'http://purl.org/sipwise/ngcp-api/#rel-partycallcontrols';
}
__PACKAGE__->config(
@ -104,9 +105,73 @@ sub POST :Allow {
"Failed to handle a party call control request.");
last;
}
} elsif ($resource->{type} eq "sms") {
my $error_msg;
my $callid = $resource->{callid};
my $status = $resource->{status};
my $token = $resource->{token};
my $sms;
try {
if($c->user->roles eq "reseller") {
my $sms_rs = $c->model('DB')->resultset('sms_journal')->search({
'me.id' => $callid,
'pcc_status' => 'pending',
'contact.reseller_id' => $c->user->reseller_id,
},{
join => { 'provisioning_voip_subscriber' => { 'voip_subscriber' => { 'contract' => 'contact' } } }
});
$sms = $sms_rs->first;
} else {
$sms = $c->model('DB')->resultset('sms_journal')->search({
'me.id' => $callid,
'pcc_token' => $token,
'pcc_status' => 'pending',
})->first;
}
} catch($e) {
$c->log->error("failed to handle a party call control request: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request.");
last;
}
unless($sms) {
$c->log->error("failed to find sms with id $callid and token $token");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Failed to find sms with callid $callid and given token");
last;
}
if($status eq "ACCEPT") {
$c->log->info("status for pcc sms of $callid is $status, forward sms");
try {
NGCP::Panel::Utils::SMS::send_sms(
c => $c,
caller => $sms->caller,
callee => $sms->callee,
text => $sms->text,
coding => $sms->coding,
err_code => sub {$error_msg = shift;},
);
$sms->update({ pcc_status => "complete" });
} catch($e) {
$c->log->error("failed to handle a party call control request: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request.");
last;
}
} else {
$c->log->info("status for pcc sms of $callid is $status, don't forward sms");
try {
$sms->update({ pcc_status => "complete" });
} catch($e) {
$c->log->error("failed to handle a party call control request: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request.");
last;
}
}
} else {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request of unknown type.");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Invalid party call control type, must be 'pcc' or 'sms'.");
last;
}

@ -6,6 +6,11 @@ use parent 'Catalyst::Controller';
use Time::Period;
use File::FnMatch qw(:fnmatch);
use Encode qw/decode/;
use UUID;
use NGCP::Panel::Utils::Preferences;
use NGCP::Panel::Utils::PartyCallControl;
use NGCP::Panel::Utils::SMS;
#sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) {
sub auto {
@ -67,12 +72,38 @@ sub receive :Chained('list') :PathPart('receive') :Args(0) {
die "no_subscriber_found";
}
my $pcc_url = $c->config->{pcc}->{url};
my $pcc_timeout = $c->config->{pcc}->{timeout};
my $pcc_enabled = 0;
my ($pcc_uuid, $pcc_token);
UUID::generate($pcc_uuid);
UUID::unparse($pcc_uuid, $pcc_token);
my $fwd_pref_rs = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, attribute => 'party_call_control',
prov_subscriber => $prov_dbalias->subscriber,
);
if($fwd_pref_rs && $fwd_pref_rs->first && $fwd_pref_rs->first->value) {
$pcc_enabled = 1;
} else {
$fwd_pref_rs = NGCP::Panel::Utils::Preferences::get_dom_preference_rs(
c => $c, attribute => 'party_call_control',
prov_domain => $prov_dbalias->domain,
);
if($fwd_pref_rs && $fwd_pref_rs->first && $fwd_pref_rs->first->value) {
$pcc_enabled = 1;
}
}
$c->log->info("pcc is set to $pcc_enabled for prov subscriber id " . $prov_dbalias->subscriber_id);
my $created_item = $c->model('DB')->resultset('sms_journal')->create({
subscriber_id => $prov_dbalias->subscriber_id,
direction => "in",
caller => $from,
callee => $to,
text => $text,
pcc_status => "none",
pcc_token => $pcc_token,
coding => $coding,
});
# check for cfs
@ -154,27 +185,56 @@ sub receive :Chained('list') :PathPart('receive') :Args(0) {
$dst =~ s/^sip:(.+)\@.+$/$1/;
$c->log->info(">>>> forward sms to $dst");
# feed back into kannel
my $error_msg;
NGCP::Panel::Utils::SMS::send_sms(
c => $c,
caller => $to, # use the original to as new from
callee => $dst,
text => $text,
coding => $coding,
err_code => sub {$error_msg = shift;},
);
my $pcc_status = $pcc_enabled ? "pending" : "none";
my $fwd_item = $c->model('DB')->resultset('sms_journal')->create({
subscriber_id => $prov_dbalias->subscriber_id,
direction => "forward",
caller => $to,
callee => $dst,
text => $text,
pcc_status => $pcc_status,
pcc_token => $pcc_token,
coding => $coding,
});
if($pcc_enabled && $pcc_url) {
try {
my $ret = NGCP::Panel::Utils::PartyCallControl::dispatch(
c => $c,
url => $pcc_url,
timeout => $pcc_timeout,
id => $fwd_item->id,
from => $from,
to => $to,
type => "sms",
text => $text,
token => $pcc_token,
);
unless($ret) {
$c->log->error("failed to dispatch pcc request");
$fwd_item->update({ pcc_status => "failed" });
}
} catch($e) {
$c->log->error("failed to dispatch pcc request: $e");
$fwd_item->update({ pcc_status => "failed" });
}
} else {
# no 3rd party call control, feed back into kannel
my $error_msg;
NGCP::Panel::Utils::SMS::send_sms(
c => $c,
caller => $to, # use the original to as new from
callee => $dst,
text => $text,
coding => $coding,
err_code => sub {$error_msg = shift;},
);
}
}
});
} catch($e) {
$c->log->error("Failed to store received SMS message.");
$c->log->error("Failed to handle received SMS message.");
$c->log->debug($e);
}

@ -0,0 +1,44 @@
package NGCP::Panel::Utils::PartyCallControl;
use Sipwise::Base;
use LWP::UserAgent;
use URI;
use JSON;
sub dispatch {
my (%args) = @_;
my $c = $args{c};
my $url = $args{url};
my $timeout = $args{timeout};
my $id = $args{id};
my $type = $args{type};
my $from = $args{from};
my $to = $args{to};
my $text = $args{text};
my $token = $args{token};
# TODO: dispatch asynchronously!
my $ua = LWP::UserAgent->new(
#ssl_opts => { verify_hostname => 0, SSL_verify_mode => 0 },
timeout => $timeout,
);
$c->log->info("sending pcc request for $type with id $id to $url");
my $req = HTTP::Request->new(POST => $url);
$req->header('Content-Type' => 'application/json');
$req->content(to_json({
actualMsisdn => $to,
callingMsisdn => $from,
callid => $id,
type => $type,
token => $token,
$type eq "sms" ? (text => $text) : (),
}));
my $res = $ua->request($req);
$c->log->info("sending pcc request " . ($res->is_success ? "succeeded" : "failed"));
if ($res->is_success) {
return 1;
}
return;
}
1;

@ -322,7 +322,7 @@ sub party_call_control {
<methodName>postDSMEvent</methodName>
<params>
<param>
<value><string>pcc_$call_id</string></value>
<value><string>pcc_$callid</string></value>
</param>
<param>
<value><array><data>

Loading…
Cancel
Save