mirror of https://github.com/sipwise/vmnotify.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.2 KiB
251 lines
6.2 KiB
#!/usr/bin/perl -w
|
|
########################################################################
|
|
# vmnotify - An Asterisk-VoiceMail compatible MWI notification script
|
|
# (c) 2017 Sipwise GmbH. All rights reserved.
|
|
#
|
|
# Author: Kirill Solomko <ksolomko@sipwise.com>
|
|
#
|
|
########################################################################
|
|
use strict;
|
|
use warnings;
|
|
use English;
|
|
use Readonly;
|
|
use Log::Log4perl qw(:easy);
|
|
use POSIX qw(strftime);
|
|
use Readonly;
|
|
use Config::Any;
|
|
use Sys::Syslog qw(:DEFAULT :macros setlogsock);
|
|
use IO::Socket;
|
|
use Data::UUID;
|
|
use Data::Dumper;
|
|
use HTTP::Request;
|
|
use LWP::UserAgent;
|
|
use JSON;
|
|
use IO::Socket::SSL;
|
|
|
|
unless (scalar @ARGV) {
|
|
print <<USAGE;
|
|
==
|
|
vmnotify - An Asterisk-VoiceMail compatible MWI notification script
|
|
==
|
|
$PROGRAM_NAME [options]
|
|
Options:
|
|
[basic]
|
|
<context> - voicemail context (default: "default")
|
|
<user> - destination user
|
|
<new messages> - amount of new messages
|
|
[old messages] - amount of old messages
|
|
[urgent messages] - amount of urgent messages
|
|
|
|
[extended]
|
|
<msgnum> - message number
|
|
<from> - from user
|
|
<date> - datetime string
|
|
<duration> - mesasge duration
|
|
USAGE
|
|
exit 0;
|
|
}
|
|
|
|
Readonly my $CONF_FILE => '/etc/ngcp-vmnotify/vmnotify.conf';
|
|
|
|
my %CONFIG = %{
|
|
Config::Any->load_files({
|
|
files => [ $CONF_FILE ],
|
|
use_ext => 1
|
|
})->[0]->{$CONF_FILE}
|
|
or do {
|
|
log_syslog(
|
|
"$PROGRAM_NAME error: Cannot load config $CONF_FILE: $ERRNO");
|
|
exit 1;
|
|
};
|
|
};
|
|
|
|
my $debug = $CONFIG{DEBUG} ? "DEBUG" : "INFO";
|
|
|
|
Log::Log4perl->init(\<<EOF);
|
|
log4perl.category.vmnotify=$debug, SYSLOG, SCREEN
|
|
|
|
log4perl.appender.SYSLOG=Log::Dispatch::Syslog
|
|
log4perl.appender.SYSLOG.facility=local0
|
|
log4perl.appender.SYSLOG.ident=vmnotify
|
|
log4perl.appender.SYSLOG.layout=PatternLayout
|
|
log4perl.appender.SYSLOG.layout.ConversionPattern=%-5p %m%n
|
|
|
|
log4perl.appender.SCREEN=Log::Log4perl::Appender::Screen
|
|
log4perl.appender.SCREEN.mode=append
|
|
log4perl.appender.SCREEN.layout=PatternLayout
|
|
log4perl.appender.SCREEN.layout.ConversionPattern=%-5p %m%n
|
|
EOF
|
|
|
|
my $log = Log::Log4perl->get_logger("vmnotify");
|
|
my %data = ();
|
|
|
|
#----------------------------------------------------------------------
|
|
sub log_syslog {
|
|
my $str = shift;
|
|
|
|
setlogsock "native", "unix", "udp";
|
|
openlog $PROGRAM_NAME, "pid", LOG_DEBUG;
|
|
syslog LOG_ERR, '%s', $str ;
|
|
|
|
return;
|
|
}
|
|
|
|
sub gen_callid {
|
|
my $self = shift;
|
|
|
|
return Data::UUID->create_str();
|
|
}
|
|
|
|
sub gen_branchid {
|
|
my @list = ("a".."z",0..9,"A".."Z");
|
|
return "z9hG4bK" . join "",
|
|
map { $list[int(rand($#list))] } (1..8);
|
|
}
|
|
|
|
sub send_mwi_notify {
|
|
|
|
open(my $fh, "<", $CONFIG{SIPFILE})
|
|
or die "Cannot open file: $CONFIG{SIPFILE}";
|
|
binmode $fh;
|
|
my $mwi;
|
|
while (<$fh>) {
|
|
$_ =~ s/([^\r])\n/$1\r\n/;
|
|
$mwi .= $_;
|
|
}
|
|
close $fh;
|
|
|
|
die "Empty MWI. Cannot send SIP MWI notification\n" unless $mwi;
|
|
|
|
my $log_str = sprintf <<EOF,
|
|
vmnotify to=%s: context=%s new=%d old=%d urgent=%d
|
|
EOF
|
|
@data{qw(user context new old urgent)};
|
|
chomp $log_str;
|
|
|
|
my %macros = (
|
|
body_mw => "Messages-Waiting: ". ($data{new} ? "yes" : "no"),
|
|
body_vm => "Voice-Message: $data{new}/$data{old} ($data{urgent}/0)",
|
|
call_id => $data{callid},
|
|
mbid => $data{user},
|
|
branch => gen_branchid(),
|
|
user => $data{user},
|
|
dsthost => $CONFIG{SERVER},
|
|
|
|
);
|
|
|
|
$macros{bodylen} = 2+length($macros{body_mw})+2+length($macros{body_vm})+2;
|
|
|
|
map { $mwi =~ s/\$$_\$/$macros{$_}/gi; } keys %macros;
|
|
|
|
my $sock = IO::Socket::INET->new(PeerAddr => $CONFIG{SERVER},
|
|
LocalAddr => $CONFIG{LOCAL_IP},
|
|
Proto => 'udp',
|
|
TimeOut => 3,
|
|
Blocking => 0)
|
|
or die sprintf "Cannot send %s server=%s error=%s\n",
|
|
$log_str, $CONFIG{SERVER}, $ERRNO;
|
|
|
|
$sock->send($mwi)
|
|
or die sprintf "Cannot send %s error=%s\n", $log_str, $ERRNO;
|
|
|
|
$sock->close();
|
|
|
|
$log->debug($log_str);
|
|
|
|
return;
|
|
}
|
|
|
|
sub send_ext_notify {
|
|
|
|
my $url = $CONFIG{EXT_SERVER_URL} || return;
|
|
|
|
my %url_ph = (
|
|
prefix => 'voicemail',
|
|
suffix => 'notify',
|
|
caller => $data{from},
|
|
caleee => $data{user},
|
|
callid => $data{callid},
|
|
token => '',
|
|
);
|
|
|
|
foreach my $v (qw(prefix suffix caller callee callid token)) {
|
|
my $t = $url_ph{$v} ? $url_ph{$v}."/" : "";
|
|
$url =~ s/\$\{$v\}/$t/g;
|
|
}
|
|
|
|
my $ua = new LWP::UserAgent;
|
|
$ua->agent('NGCP vmnotify 1.0');
|
|
|
|
$ua->ssl_opts(
|
|
verify_hostname => 0,
|
|
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
|
|
);
|
|
|
|
my $r = new HTTP::Request("POST", $url);
|
|
$r->header('Content-Type', 'application/json');
|
|
|
|
my $json = {
|
|
caller => $data{from},
|
|
callee => $data{user},
|
|
recording_id => $data{msgnum},
|
|
timestamp => $data{date},
|
|
duration => $data{duration},
|
|
};
|
|
|
|
$r->content(encode_json $json);
|
|
|
|
my $res = $ua->request($r);
|
|
|
|
my $log_str = sprintf <<EOF,
|
|
ext vmnotify url=%s from=%s to=%s msgnum=%d date=%s duration=%d
|
|
EOF
|
|
$url, @data{qw(from user msgnum date duration)};
|
|
chomp $log_str;
|
|
|
|
if ($res->is_success) {
|
|
$log->debug($log_str);
|
|
} else {
|
|
die sprintf "Cannot send %s error=%s\n", $log_str, $res->status_line
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
sub main {
|
|
eval {
|
|
die "Incorrect arguments list" if $#ARGV < 2;
|
|
|
|
my $idx = 0;
|
|
foreach my $arg (qw(context user new old urgent)) {
|
|
$data{$arg} = $ARGV[$idx] // 0;
|
|
$idx++;
|
|
}
|
|
|
|
my $extended = 1;
|
|
foreach my $arg (qw(msgnum from date duration)) {
|
|
$data{$arg} = $ARGV[$idx] or $extended = 0;
|
|
$idx++;
|
|
}
|
|
|
|
$data{callid} = gen_callid().'@voip.sipwise.local';
|
|
|
|
send_mwi_notify();
|
|
if ($extended &&
|
|
$CONFIG{EXT_NOTIFY} && $CONFIG{EXT_NOTIFY} eq "yes") {
|
|
send_ext_notify();
|
|
}
|
|
};
|
|
if ($EVAL_ERROR) {
|
|
$log->error($EVAL_ERROR);
|
|
exit 1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
main();
|
|
|
|
exit 0;
|
|
|