diff --git a/lib/NGCP/Panel/Controller/API/PartyCallControls.pm b/lib/NGCP/Panel/Controller/API/PartyCallControls.pm
index 9bdd83085a..6b91432a3b 100644
--- a/lib/NGCP/Panel/Controller/API/PartyCallControls.pm
+++ b/lib/NGCP/Panel/Controller/API/PartyCallControls.pm
@@ -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;
}
diff --git a/lib/NGCP/Panel/Controller/InternalSms.pm b/lib/NGCP/Panel/Controller/InternalSms.pm
index a20168145f..959b5accb4 100644
--- a/lib/NGCP/Panel/Controller/InternalSms.pm
+++ b/lib/NGCP/Panel/Controller/InternalSms.pm
@@ -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);
}
diff --git a/lib/NGCP/Panel/Utils/PartyCallControl.pm b/lib/NGCP/Panel/Utils/PartyCallControl.pm
new file mode 100644
index 0000000000..6aaf8b6b4e
--- /dev/null
+++ b/lib/NGCP/Panel/Utils/PartyCallControl.pm
@@ -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;
diff --git a/lib/NGCP/Panel/Utils/Sems.pm b/lib/NGCP/Panel/Utils/Sems.pm
index 1841d15889..3271b9c23b 100644
--- a/lib/NGCP/Panel/Utils/Sems.pm
+++ b/lib/NGCP/Panel/Utils/Sems.pm
@@ -322,7 +322,7 @@ sub party_call_control {
postDSMEvent
- pcc_$call_id
+ pcc_$callid