mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 21:59:53 +05:00
Adding tutorial_osips_calls file, removing obsolete data/tutorials/osips_async, optimizing kam_calls test file
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
# Real-time Charging System for Telecom & ISP environments
|
||||
# Copyright (C) ITsysCOM GmbH
|
||||
#
|
||||
# This file contains the default configuration hardcoded into CGRateS.
|
||||
# This is what you get when you load CGRateS with an empty configuration file.
|
||||
|
||||
[rater]
|
||||
enabled = true # Enable RaterCDRSExportPath service: <true|false>.
|
||||
|
||||
[scheduler]
|
||||
enabled = true # Starts Scheduler service: <true|false>.
|
||||
|
||||
[cdrs]
|
||||
enabled = true # Start the CDR Server service: <true|false>.
|
||||
mediator = internal # Address where to reach the Mediator. Empty for disabling mediation. <""|internal>
|
||||
|
||||
[mediator]
|
||||
enabled = true # Starts Mediator service: <true|false>.
|
||||
|
||||
[cdrstats]
|
||||
enabled = true # Starts the cdrstats service: <true|false>
|
||||
queue_length = 5 # Number of items in the stats buffer
|
||||
time_window = 5m # Will only keep the CDRs who's call setup time is not older than time.Now()-TimeWindow
|
||||
|
||||
[session_manager]
|
||||
enabled = true # Starts SessionManager service: <true|false>
|
||||
switch_type = opensips # Defines the type of switch behind: <freeswitch>
|
||||
cdrs = internal # Address where to reach the CDR server for CDR processing
|
||||
|
||||
[opensips]
|
||||
# listen_udp = 127.0.0.1:2020 # Address where to listen for datagram events coming from OpenSIPS
|
||||
# mi_addr = 127.0.0.1:8020 # Adress where to reach OpenSIPS mi_datagram module
|
||||
# reconnects = 3 # Number of attempts on connect failure.
|
||||
|
||||
[history_server]
|
||||
enabled = true # Starts History service: <true|false>.
|
||||
history_dir = /tmp/cgrates/history # Location on disk where to store history files.
|
||||
|
||||
[history_agent]
|
||||
enabled = true # Starts History as a client: <true|false>.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# defaults file for CGRateS real-time charging system
|
||||
|
||||
# start CGRateS init.d script?
|
||||
# starts with "true"
|
||||
ENABLE=true
|
||||
|
||||
# Start with specific user/group
|
||||
#USER=cgrates
|
||||
#GROUP=cgrates
|
||||
|
||||
# what extra options to give cgrates binary?
|
||||
# See cgr-engine -h for options
|
||||
ENGINE_OPTS='-config=/usr/share/cgrates/tutorials/osips_event/cgrates/etc/cgrates/cgrates.cfg'
|
||||
|
||||
# Don't forget to create an appropriate config file,
|
||||
# else the CGRateS system will not start.
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
#! /bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: cgrates
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: CGRateS real-time charging system
|
||||
# Description: Control CGRateS - carrier grade real-time charging system
|
||||
### END INIT INFO
|
||||
|
||||
# Author: DanB <danb@cgrates.org>
|
||||
#
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
RUNDIR=/tmp/$NAME/run
|
||||
PIDFILE=$RUNDIR/cgr-engine.pid
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="CGRateS real-time charging system"
|
||||
NAME=cgrates
|
||||
DAEMON=/usr/bin/cgr-engine
|
||||
USER=cgrates
|
||||
GROUP=cgrates
|
||||
TUTFOLDER=/usr/share/cgrates/tutorials/osips_event/cgrates
|
||||
ENGINE_OPTS=""
|
||||
PIDFILE=/tmp/cgr-engine_osips_event.pid
|
||||
SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME
|
||||
DEFAULTS=$TUTFOLDER/etc/default/$NAME
|
||||
ENABLE=false
|
||||
HISTDIR=/tmp/$NAME/history
|
||||
CDREDIR=/tmp/$NAME/cdre
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r $DEFAULTS ] && . $DEFAULTS
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
|
||||
# and status_of_proc is working.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
if [ "$ENABLE" != "true" ]; then
|
||||
echo "$DESC not yet configured. Edit $DEFAULTS first."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install the run folder
|
||||
if [ ! -d $RUNDIR ]; then
|
||||
mkdir -p $RUNDIR
|
||||
chown $USER:$GROUP $RUNDIR
|
||||
fi
|
||||
# Install the cdre folder
|
||||
if [ ! -d $CDREDIR ]; then
|
||||
mkdir -p $CDREDIR
|
||||
chown $USER:$GROUP $CDREDIR
|
||||
fi
|
||||
# Install the history folder
|
||||
if [ ! -d $HISTDIR ]; then
|
||||
mkdir -p $HISTDIR
|
||||
chown $USER:$GROUP $HISTDIR
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --exec $DAEMON --chuid $USER:$GROUP --background -- \
|
||||
$ENGINE_OPTS \
|
||||
|| return 2
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
# and if the daemon is only ever run from this initscript.
|
||||
# If the above conditions are not satisfied then add some other code
|
||||
# that waits for the process to drop all resources that could be
|
||||
# needed by services started subsequently. A last resort is to
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
#reload|force-reload)
|
||||
#
|
||||
# If do_reload() is not implemented then leave this commented out
|
||||
# and leave 'force-reload' as an alias for 'restart'.
|
||||
#
|
||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
#do_reload
|
||||
#log_end_msg $?
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# OpenSIPS startup options
|
||||
#
|
||||
|
||||
# Set to yes to enable opensips, once configured properly.
|
||||
RUN_OPENSIPS=yes
|
||||
|
||||
# User to run as
|
||||
USER=opensips
|
||||
|
||||
# Group to run as
|
||||
GROUP=opensips
|
||||
|
||||
# Amount of shared memory to allocate for the running OpenSIPS server (in Mb)
|
||||
S_MEMORY=64
|
||||
|
||||
# Amount of pkg memory to allocate for the running OpenSIPS server (in Mb)
|
||||
P_MEMORY=4
|
||||
|
||||
# Enable the server to leave a core file when it crashes.
|
||||
# Set this to 'yes' to enable OpenSIPS to leave a core file when it crashes
|
||||
# or 'no' to disable this feature. This option is case sensitive and only
|
||||
# accepts 'yes' and 'no' and only in lowercase letters.
|
||||
# On some systems (e.g. Ubuntu 6.10, Debian 4.0) it is necessary to specify
|
||||
# a directory for the core files to get a dump. Look into the opensips
|
||||
# init file for an example configuration.
|
||||
DUMP_CORE=no
|
||||
@@ -1,192 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: opensips
|
||||
# Required-Start: $syslog $network $local_fs $time
|
||||
# Required-Stop: $syslog $network $local_fs
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start the OpenSIPS SIP server
|
||||
# Description: Start the OpenSIPS SIP server
|
||||
### END INIT INFO
|
||||
#
|
||||
# TODO:
|
||||
# The following fields should be added (and completed):
|
||||
# Should-Start: postgresql mysql radius
|
||||
# Should-Stop: postgresql mysql radius
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DAEMON=/usr/sbin/opensips
|
||||
NAME=opensips
|
||||
DESC=opensips
|
||||
TUTFOLDER=/usr/share/cgrates/tutorials/osips_event/opensips
|
||||
CFGFILE=$TUTFOLDER/etc/opensips/opensips.cfg
|
||||
M4CFGFILE=$TUTFOLDER/etc/opensips/opensips.m4
|
||||
M4ARCHIVEDIR=$TUTFOLDER/etc/opensips/archive
|
||||
HOMEDIR=/var/run/opensips
|
||||
PIDFILE=$HOMEDIR/$NAME.pid
|
||||
DEFAULTS=$TUTFOLDER/etc/default/opensips
|
||||
RUN_OPENSIPS=no
|
||||
|
||||
# Do not start opensips if fork=no is set in the config file
|
||||
# otherwise the boot process will just stop
|
||||
check_fork ()
|
||||
{
|
||||
if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFGFILE; then
|
||||
echo "Not starting $DESC: fork=no specified in config file; run /etc/init.d/opensips debug instead"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_opensips_config ()
|
||||
{
|
||||
# Check if opensips configuration is valid before starting the server
|
||||
set +e
|
||||
out=$($DAEMON -c 2>&1 > /dev/null)
|
||||
retcode=$?
|
||||
set -e
|
||||
if [ "$retcode" != '0' ]; then
|
||||
echo "Not starting $DESC: invalid configuration file!"
|
||||
echo -e "\n$out\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
create_radius_seqfile ()
|
||||
{
|
||||
# Create a radius sequence file to be used by the radius client if
|
||||
# radius accounting is enabled. This is needed to avoid any issue
|
||||
# with the file not being writable if opensips first starts as user
|
||||
# root because DUMP_CORE is enabled and creates this file as user
|
||||
# root and then later it switches back to user opensips and cannot
|
||||
# write to the file. If the file exists before opensips starts, it
|
||||
# won't change it's ownership and will be writable for both root
|
||||
# and opensips, no matter what options are chosen at install time
|
||||
RADIUS_SEQ_FILE=/var/run/opensips/opensips_radius.seq
|
||||
if [ -d /var/run/opensips ]; then
|
||||
chown ${USER}:${GROUP} /var/run/opensips
|
||||
|
||||
if [ ! -f $RADIUS_SEQ_FILE ]; then
|
||||
touch $RADIUS_SEQ_FILE
|
||||
fi
|
||||
|
||||
chown ${USER}:${GROUP} $RADIUS_SEQ_FILE
|
||||
chmod 660 $RADIUS_SEQ_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
test -f $DAEMON || exit 0
|
||||
|
||||
# Load startup options if available
|
||||
if [ -f $DEFAULTS ]; then
|
||||
. $DEFAULTS || true
|
||||
fi
|
||||
|
||||
if [ "$RUN_OPENSIPS" != "yes" ]; then
|
||||
echo "OpenSIPS not yet configured. Edit /etc/default/opensips first."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
S_MEMORY=$((`echo $S_MEMORY | sed -e 's/[^0-9]//g'`))
|
||||
P_MEMORY=$((`echo $P_MEMORY | sed -e 's/[^0-9]//g'`))
|
||||
[ -z "$USER" ] && USER=opensips
|
||||
[ -z "$GROUP" ] && GROUP=opensips
|
||||
[ $S_MEMORY -le 0 ] && S_MEMORY=32
|
||||
[ $P_MEMORY -le 0 ] && P_MEMORY=32
|
||||
|
||||
if test "$DUMP_CORE" = "yes" ; then
|
||||
# set proper ulimit
|
||||
ulimit -c unlimited
|
||||
|
||||
# directory for the core dump files
|
||||
# COREDIR=/home/corefiles
|
||||
# [ -d $COREDIR ] || mkdir $COREDIR
|
||||
# chmod 777 $COREDIR
|
||||
# echo "$COREDIR/core.%e.sig%s.%p" > /proc/sys/kernel/core_pattern
|
||||
fi
|
||||
|
||||
OPTIONS="-f $CFGFILE -P $PIDFILE -m $S_MEMORY -M $P_MEMORY -u $USER -g $GROUP"
|
||||
|
||||
case "$1" in
|
||||
start|debug)
|
||||
check_opensips_config
|
||||
create_radius_seqfile
|
||||
|
||||
if [ "$1" != "debug" ]; then
|
||||
check_fork
|
||||
fi
|
||||
|
||||
# dirs under /var/run can go away on reboots.
|
||||
mkdir -p "$HOMEDIR"
|
||||
chmod 775 "$HOMEDIR"
|
||||
chown "$USER:$GROUP" "$HOMEDIR" >/dev/null 2>&1 || true
|
||||
|
||||
# Generate config from M4
|
||||
if [ -f $M4CFGFILE ]; then
|
||||
m4 -Q $M4CFGFILE >$CFGFILE.tmp
|
||||
if [ $? != 0 ]; then
|
||||
echo "Cannot process m4 macro"
|
||||
rm "$CFGFILE.tmp"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -e $CFGFILE ] || touch $CFGFILE
|
||||
|
||||
# compare configs
|
||||
if [ `md5sum $CFGFILE|awk '{print $1}'` != `md5sum $CFGFILE.tmp|awk '{print $1}'` ]; then
|
||||
mkdir -p "$M4ARCHIVEDIR"
|
||||
mv "$CFGFILE" "$M4ARCHIVEDIR/$NAME.cfg-`date +%Y%m%d_%H%M%S`"
|
||||
fi
|
||||
|
||||
mv "$CFGFILE.tmp" "$CFGFILE"
|
||||
chown $USER:$GROUP $CFGFILE
|
||||
chmod 640 $CFGFILE
|
||||
fi
|
||||
|
||||
echo -n "Starting $DESC: $NAME"
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE \
|
||||
--exec $DAEMON -- $OPTIONS || echo -n " already running"
|
||||
echo "."
|
||||
;;
|
||||
stop)
|
||||
echo -n "Stopping $DESC: $NAME"
|
||||
start-stop-daemon --oknodo --stop --quiet --pidfile $PIDFILE \
|
||||
--exec $DAEMON
|
||||
echo "."
|
||||
;;
|
||||
restart|force-reload)
|
||||
check_opensips_config
|
||||
create_radius_seqfile
|
||||
|
||||
echo -n "Restarting $DESC: $NAME"
|
||||
start-stop-daemon --oknodo --stop --quiet --pidfile \
|
||||
$PIDFILE --exec $DAEMON
|
||||
sleep 1
|
||||
start-stop-daemon --start --quiet --pidfile \
|
||||
$PIDFILE --exec $DAEMON -- $OPTIONS
|
||||
echo "."
|
||||
;;
|
||||
status)
|
||||
echo -n "Status of $DESC: "
|
||||
if [ ! -r "$PIDFILE" ]; then
|
||||
echo "$NAME is not running."
|
||||
exit 3
|
||||
fi
|
||||
if read pid < "$PIDFILE" && ps -p "$pid" > /dev/null 2>&1; then
|
||||
echo "$NAME is running."
|
||||
exit 0
|
||||
else
|
||||
echo "$NAME is not running but $PIDFILE exists."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
N=/etc/init.d/$NAME
|
||||
echo "Usage: $N {start|stop|restart|force-reload|debug|status}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -1,335 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# OpenSIPS residential configuration script
|
||||
# by OpenSIPS Solutions <team@opensips-solutions.com>
|
||||
#
|
||||
# This script was generated via "make menuconfig", from
|
||||
# the "Residential" scenario.
|
||||
# You can enable / disable more features / functionalities by
|
||||
# re-generating the scenario with different options.#
|
||||
#
|
||||
# Please refer to the Core CookBook at:
|
||||
# http://www.opensips.org/Resources/DocsCookbooks
|
||||
# for a explanation of possible statements, functions and parameters.
|
||||
#
|
||||
|
||||
|
||||
####### Global Parameters #########
|
||||
|
||||
debug=3
|
||||
log_stderror=no
|
||||
log_facility=LOG_LOCAL0
|
||||
|
||||
fork=yes
|
||||
children=4
|
||||
|
||||
auto_aliases=no
|
||||
|
||||
disable_tcp=yes
|
||||
disable_tls=yes
|
||||
|
||||
|
||||
####### Modules Section ########
|
||||
|
||||
#set module path
|
||||
mpath="/usr/lib/opensips/modules"
|
||||
|
||||
#### SIGNALING module
|
||||
loadmodule "signaling.so"
|
||||
|
||||
#### StateLess module
|
||||
loadmodule "sl.so"
|
||||
|
||||
#### Transaction Module
|
||||
loadmodule "tm.so"
|
||||
modparam("tm", "fr_timer", 5)
|
||||
modparam("tm", "fr_inv_timer", 30)
|
||||
modparam("tm", "restart_fr_on_each_reply", 0)
|
||||
modparam("tm", "onreply_avp_mode", 1)
|
||||
|
||||
#### Record Route Module
|
||||
loadmodule "rr.so"
|
||||
/* do not append from tag to the RR (no need for this script) */
|
||||
modparam("rr", "append_fromtag", 0)
|
||||
|
||||
#### MAX ForWarD module
|
||||
loadmodule "maxfwd.so"
|
||||
|
||||
#### SIP MSG OPerationS module
|
||||
loadmodule "sipmsgops.so"
|
||||
|
||||
#### FIFO Management Interface
|
||||
loadmodule "mi_fifo.so"
|
||||
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
|
||||
modparam("mi_fifo", "fifo_mode", 0666)
|
||||
|
||||
loadmodule "mi_datagram.so"
|
||||
modparam("mi_datagram", "socket_name", "udp:127.0.0.1:8020")
|
||||
|
||||
#### Eventdatagram module
|
||||
loadmodule "event_datagram.so"
|
||||
|
||||
#### URI module
|
||||
loadmodule "uri.so"
|
||||
modparam("uri", "use_uri_table", 0)
|
||||
|
||||
#### USeR LOCation module
|
||||
loadmodule "usrloc.so"
|
||||
modparam("usrloc", "nat_bflag", "NAT")
|
||||
modparam("usrloc", "db_mode", 0)
|
||||
|
||||
#### REGISTRAR module
|
||||
loadmodule "registrar.so"
|
||||
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
|
||||
|
||||
/* uncomment the next line not to allow more than 10 contacts per AOR */
|
||||
#modparam("registrar", "max_contacts", 10)
|
||||
|
||||
#### DIALOG module
|
||||
loadmodule "dialog.so"
|
||||
modparam("dialog", "dlg_match_mode", 1)
|
||||
modparam("dialog", "default_timeout", 21600) # 6 hours timeout
|
||||
modparam("dialog", "db_mode", 0)
|
||||
|
||||
|
||||
#### ACCounting module
|
||||
loadmodule "acc.so"
|
||||
/* what special events should be accounted ? */
|
||||
modparam("acc", "early_media", 0)
|
||||
modparam("acc", "report_cancels", 1)
|
||||
modparam("acc", "cdr_flag", "CDR")
|
||||
modparam("acc", "evi_flag", "CDR")
|
||||
modparam("acc", "evi_missed_flag", "CDR")
|
||||
modparam("acc", "evi_extra",
|
||||
"cgr_reqtype=$avp(cgr_reqtype);
|
||||
cgr_account=$avp(cgr_account);
|
||||
cgr_subject=$avp(cgr_subject);
|
||||
cgr_destination=$avp(cgr_destination);
|
||||
originalUri=$ou")
|
||||
|
||||
#### CfgUtils module
|
||||
loadmodule "cfgutils.so"
|
||||
|
||||
#### CacheDB Local
|
||||
loadmodule "cachedb_local.so"
|
||||
|
||||
|
||||
####### Routing Logic ########
|
||||
|
||||
startup_route {
|
||||
subscribe_event("E_OPENSIPS_START", "udp:127.0.0.1:2020");
|
||||
raise_event("E_OPENSIPS_START");
|
||||
}
|
||||
|
||||
# main request routing logic
|
||||
|
||||
route{
|
||||
|
||||
|
||||
if (!mf_process_maxfwd_header("10")) {
|
||||
sl_send_reply("483","Too Many Hops");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (has_totag()) {
|
||||
# sequential request withing a dialog should
|
||||
# take the path determined by record-routing
|
||||
if (loose_route()) {
|
||||
if (is_method("BYE")) {
|
||||
#setflag(CDR); # do accounting ...
|
||||
} else if (is_method("INVITE")) {
|
||||
# even if in most of the cases is useless, do RR for
|
||||
# re-INVITEs alos, as some buggy clients do change route set
|
||||
# during the dialog.
|
||||
record_route();
|
||||
}
|
||||
|
||||
|
||||
|
||||
# route it out to whatever destination was set by loose_route()
|
||||
# in $du (destination URI).
|
||||
route(relay);
|
||||
} else {
|
||||
|
||||
if ( is_method("ACK") ) {
|
||||
if ( t_check_trans() ) {
|
||||
# non loose-route, but stateful ACK; must be an ACK after
|
||||
# a 487 or e.g. 404 from upstream server
|
||||
t_relay();
|
||||
exit;
|
||||
} else {
|
||||
# ACK without matching transaction ->
|
||||
# ignore and discard
|
||||
exit;
|
||||
}
|
||||
}
|
||||
sl_send_reply("404","Not here");
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
# CANCEL processing
|
||||
if (is_method("CANCEL"))
|
||||
{
|
||||
if (t_check_trans())
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
t_check_trans();
|
||||
|
||||
if ( !(is_method("REGISTER") ) ) {
|
||||
|
||||
if (from_uri==myself)
|
||||
|
||||
{
|
||||
|
||||
} else {
|
||||
# if caller is not local, then called number must be local
|
||||
|
||||
if (!uri==myself) {
|
||||
send_reply("403","Rely forbidden");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# preloaded route checking
|
||||
if (loose_route()) {
|
||||
xlog("L_ERR",
|
||||
"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
|
||||
if (!is_method("ACK"))
|
||||
sl_send_reply("403","Preload Route denied");
|
||||
exit;
|
||||
}
|
||||
|
||||
# record routing
|
||||
if (!is_method("REGISTER|MESSAGE"))
|
||||
record_route();
|
||||
|
||||
# account only INVITEs
|
||||
if (is_method("INVITE")) {
|
||||
# create dialog with timeout
|
||||
if ( !create_dialog("B") ) {
|
||||
send_reply("500","Internal Server Error");
|
||||
exit;
|
||||
}
|
||||
setflag(CDR);
|
||||
route(CGR_HANDLER);
|
||||
}
|
||||
|
||||
if (!uri==myself) {
|
||||
append_hf("P-hint: outbound\r\n");
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
# requests for my domain
|
||||
|
||||
if (is_method("PUBLISH|SUBSCRIBE"))
|
||||
{
|
||||
sl_send_reply("503", "Service Unavailable");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_method("REGISTER"))
|
||||
{
|
||||
if ( 0 ) setflag(TCP_PERSISTENT);
|
||||
|
||||
if (!save("location"))
|
||||
sl_reply_error();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($rU==NULL) {
|
||||
# request with no Username in RURI
|
||||
sl_send_reply("484","Address Incomplete");
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
# do lookup with method filtering
|
||||
if (!lookup("location","m")) {
|
||||
t_newtran();
|
||||
t_reply("404", "Not Found");
|
||||
exit;
|
||||
}
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
|
||||
route[relay] {
|
||||
if (!t_relay()) {
|
||||
send_reply("500","Internal Error");
|
||||
};
|
||||
exit;
|
||||
}
|
||||
|
||||
route[CGR_HANDLER] {
|
||||
# These variables should be populated by script admin on need
|
||||
$avp(cgr_reqtype)="*rated";
|
||||
$avp(cgr_account)=$fU;
|
||||
$avp(cgr_subject)=$fU;
|
||||
$avp(cgr_destination)=$rU;
|
||||
switch ($avp(cgr_account)) {
|
||||
case "1002":
|
||||
$avp(cgr_reqtype)="*postpaid";
|
||||
break;
|
||||
case "1003":
|
||||
$avp(cgr_reqtype)="*pseudoprepaid";
|
||||
break;
|
||||
}
|
||||
# End of variables population
|
||||
|
||||
if $avp(cgr_reqtype)=="*pseudoprepaid" || $avp(cgr_reqtype)=="*prepaid" { #Make sure we got enough balance for the call
|
||||
|
||||
$avp(auth_keys) = "cgr_reqtype";
|
||||
$avp(auth_vals) = $avp(cgr_reqtype);
|
||||
$avp(auth_keys) = "callid";
|
||||
$avp(auth_vals) = $ci;
|
||||
$avp(auth_keys) = "from_tag";
|
||||
$avp(auth_vals) = $ft;
|
||||
$avp(auth_keys) = "cgr_account";
|
||||
$avp(auth_vals) = $avp(cgr_account);
|
||||
$avp(auth_keys) = "cgr_subject";
|
||||
$avp(auth_vals) = $avp(cgr_subject);
|
||||
$avp(auth_keys) = "cgr_destination";
|
||||
$avp(auth_vals) = $avp(cgr_destination);
|
||||
$avp(auth_keys) = "created";
|
||||
$avp(auth_vals) = $Ts;
|
||||
raise_event("E_CGR_AUTHORIZE", $avp(auth_keys), $avp(auth_vals));
|
||||
|
||||
$var(accid) = $ci+";"+$ft+";";
|
||||
$var(rply_cgr_notify) = $var(accid)+"/"+"cgr_notify"; #Key in localcache for cgr_notify
|
||||
$var(rply_cgr_maxdur) = $var(accid)+"/"+"cgr_maxdur"; #Key in localcache for cgr_maxdur
|
||||
$var(ms) = 0;
|
||||
while($var(ms) < 2000) { # Check for values set every 10 ms for maximum 2 seconds
|
||||
if cache_fetch("local", "$var(rply_cgr_notify)", $avp(cgr_notify) ) $var(ms) = 2000; # Break out
|
||||
$var(ms) = $var(ms) + 10;
|
||||
usleep("10");
|
||||
}
|
||||
if $avp(cgr_notify) == NULL { # Cannot check it in switch
|
||||
sl_send_reply("503","Prepaid controller error on notify");
|
||||
exit;
|
||||
}
|
||||
switch ($avp(cgr_notify)) {
|
||||
case "SERVER_ERROR":
|
||||
sl_send_reply("503","Prepaid controller error");
|
||||
exit;
|
||||
case "INSUFFICIENT_FUNDS":
|
||||
sl_send_reply("403", "Payment required");
|
||||
exit;
|
||||
}
|
||||
if !cache_fetch("local", "$var(rply_cgr_maxdur)", $avp(cgr_maxdur) ) {
|
||||
sl_send_reply("503","Prepaid controller error on maxdur");
|
||||
exit;
|
||||
}
|
||||
$DLG_timeout=$avp(cgr_maxdur);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"net/rpc/jsonrpc"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -131,66 +130,6 @@ func TestTutKamCallsLoadTariffPlanFromFolder(t *testing.T) {
|
||||
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
|
||||
}
|
||||
|
||||
// Check loaded stats
|
||||
func TestTutKamCallsCacheStats(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var rcvStats *utils.CacheStats
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 3, RatingProfiles: 8, Actions: 6, SharedGroups: 1, RatingAliases: 1, AccountAliases: 1, DerivedChargers: 1}
|
||||
var args utils.AttrCacheStats
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
|
||||
} else if !reflect.DeepEqual(expectedStats, rcvStats) {
|
||||
t.Errorf("Calling ApierV1.GetCacheStats expected: %v, received: %v", expectedStats, rcvStats)
|
||||
}
|
||||
}
|
||||
|
||||
// Check items age
|
||||
func TestTutKamCallsGetCachedItemAge(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var rcvAge *utils.CachedItemAge
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "1002", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.Destination > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "RP_RETAIL1", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.RatingPlan > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "*out:cgrates.org:call:*any", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.RatingProfile > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "LOG_WARNING", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.Action > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "SHARED_A", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.SharedGroup > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
/*
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "1006", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.RatingAlias > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetCachedItemAge", "1006", &rcvAge); err != nil {
|
||||
t.Error("Got error on ApierV1.GetCachedItemAge: ", err.Error())
|
||||
} else if rcvAge.RatingAlias > time.Duration(2)*time.Second || rcvAge.AccountAlias > time.Duration(2)*time.Second {
|
||||
t.Errorf("Cache too old: %d", rcvAge)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCallsAccountsBefore(t *testing.T) {
|
||||
if !*testCalls {
|
||||
@@ -233,122 +172,6 @@ func TestTutKamCallsAccountsBefore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check call costs
|
||||
func TestTutKamCallsGetCosts(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z")
|
||||
tEnd, _ := utils.ParseDate("2014-08-04T13:00:20Z")
|
||||
cd := engine.CallDescriptor{
|
||||
Direction: "*out",
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "1001",
|
||||
Account: "1001",
|
||||
Destination: "1002",
|
||||
DurationIndex: 0,
|
||||
TimeStart: tStart,
|
||||
TimeEnd: tEnd,
|
||||
}
|
||||
var cc engine.CallCost
|
||||
if err := tutKamCallsRpc.Call("Responder.GetCost", cd, &cc); err != nil {
|
||||
t.Error("Got error on Responder.GetCost: ", err.Error())
|
||||
} else if cc.Cost != 0.6 {
|
||||
t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost)
|
||||
}
|
||||
tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z")
|
||||
tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z")
|
||||
cd = engine.CallDescriptor{
|
||||
Direction: "*out",
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "1001",
|
||||
Account: "1001",
|
||||
Destination: "1002",
|
||||
DurationIndex: 0,
|
||||
TimeStart: tStart,
|
||||
TimeEnd: tEnd,
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("Responder.GetCost", cd, &cc); err != nil {
|
||||
t.Error("Got error on Responder.GetCost: ", err.Error())
|
||||
} else if cc.Cost != 0.6417 {
|
||||
t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost)
|
||||
}
|
||||
tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z")
|
||||
tEnd, _ = utils.ParseDate("2014-08-04T13:00:20Z")
|
||||
cd = engine.CallDescriptor{
|
||||
Direction: "*out",
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "1001",
|
||||
Account: "1001",
|
||||
Destination: "1003",
|
||||
DurationIndex: 0,
|
||||
TimeStart: tStart,
|
||||
TimeEnd: tEnd,
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("Responder.GetCost", cd, &cc); err != nil {
|
||||
t.Error("Got error on Responder.GetCost: ", err.Error())
|
||||
} else if cc.Cost != 1 {
|
||||
t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost)
|
||||
}
|
||||
tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z")
|
||||
tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z")
|
||||
cd = engine.CallDescriptor{
|
||||
Direction: "*out",
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "1001",
|
||||
Account: "1001",
|
||||
Destination: "1003",
|
||||
DurationIndex: 0,
|
||||
TimeStart: tStart,
|
||||
TimeEnd: tEnd,
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("Responder.GetCost", cd, &cc); err != nil {
|
||||
t.Error("Got error on Responder.GetCost: ", err.Error())
|
||||
} else if cc.Cost != 1.3 {
|
||||
t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost)
|
||||
}
|
||||
tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z")
|
||||
tEnd, _ = utils.ParseDate("2014-08-04T13:00:20Z")
|
||||
cd = engine.CallDescriptor{
|
||||
Direction: "*out",
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "1001",
|
||||
Account: "1001",
|
||||
Destination: "1004",
|
||||
DurationIndex: 0,
|
||||
TimeStart: tStart,
|
||||
TimeEnd: tEnd,
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("Responder.GetCost", cd, &cc); err != nil {
|
||||
t.Error("Got error on Responder.GetCost: ", err.Error())
|
||||
} else if cc.Cost != 1 {
|
||||
t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost)
|
||||
}
|
||||
tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z")
|
||||
tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z")
|
||||
cd = engine.CallDescriptor{
|
||||
Direction: "*out",
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "1001",
|
||||
Account: "1001",
|
||||
Destination: "1004",
|
||||
DurationIndex: 0,
|
||||
TimeStart: tStart,
|
||||
TimeEnd: tEnd,
|
||||
}
|
||||
if err := tutKamCallsRpc.Call("Responder.GetCost", cd, &cc); err != nil {
|
||||
t.Error("Got error on Responder.GetCost: ", err.Error())
|
||||
} else if cc.Cost != 1.3 {
|
||||
t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutKamCallsCdrStats(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
|
||||
467
general_tests/tutorial_osips_calls_test.go
Normal file
467
general_tests/tutorial_osips_calls_test.go
Normal file
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
Real-time Charging System for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can Storagetribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITH*out ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package general_tests
|
||||
|
||||
import (
|
||||
"net/rpc"
|
||||
"net/rpc/jsonrpc"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/apier/v1"
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
var tutOsipsCallsCfg *config.CGRConfig
|
||||
var tutOsipsCallsRpc *rpc.Client
|
||||
var tutOsipsCallsPjSuaListener *os.File
|
||||
|
||||
func TestTutOsipsCallsInitCfg(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
// Init config first
|
||||
var err error
|
||||
tutOsipsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "kamevapi", "cgrates", "etc", "cgrates"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
tutOsipsCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush()
|
||||
config.SetCgrConfig(tutOsipsCallsCfg)
|
||||
}
|
||||
|
||||
// Remove data in both rating and accounting db
|
||||
func TestTutOsipsCallsResetDataDb(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.InitDataDb(tutOsipsCallsCfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Wipe out the cdr database
|
||||
func TestTutOsipsCallsResetStorDb(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.InitStorDb(tutOsipsCallsCfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// start Kam server
|
||||
func TestTutOsipsCallsStartOsips(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
engine.KillProcName("opensips", *waitRater)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "start", 100); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Start CGR Engine
|
||||
func TestTutOsipsCallsStartEngine(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
engine.KillProcName("cgr-engine", *waitRater)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Restart Kam so we make sure reconnects are working
|
||||
func TestTutOsipsCallsRestartKam(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "restart", 200); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Connect rpc client to rater
|
||||
func TestTutOsipsCallsRpcConn(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
tutOsipsCallsRpc, err = jsonrpc.Dial("tcp", tutOsipsCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Load the tariff plan, creating accounts and their balances
|
||||
func TestTutOsipsCallsLoadTariffPlanFromFolder(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
reply := ""
|
||||
attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if reply != "OK" {
|
||||
t.Error(reply)
|
||||
}
|
||||
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCallsAccountsBefore(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply *engine.Account
|
||||
attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
|
||||
t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
|
||||
}
|
||||
attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
|
||||
t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
|
||||
}
|
||||
attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
|
||||
t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
|
||||
}
|
||||
attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
|
||||
t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
|
||||
}
|
||||
attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 0.0 { // Make sure we debitted
|
||||
t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
|
||||
}
|
||||
attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err == nil || !strings.HasSuffix(err.Error(), "does not exist") {
|
||||
t.Error("Got error on ApierV1.GetAccount: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCdrStats(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var queueIds []string
|
||||
eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetQueueIds", "", &queueIds); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetQueueIds, got error: ", err.Error())
|
||||
} else if len(eQueueIds) != len(queueIds) {
|
||||
t.Errorf("Expecting: %v, received: %v", eQueueIds, queueIds)
|
||||
}
|
||||
}
|
||||
|
||||
// Start Pjsua as listener and register it to receive calls
|
||||
func TestTutOsipsCallsStartPjsuaListener(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
acnts := []*engine.PjsuaAccount{
|
||||
&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}}
|
||||
if tutOsipsCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, *waitRater); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Call from 1001 (prepaid) to 1002
|
||||
func TestTutOsipsCallsCall1001To1002(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCall1002To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5072); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCall1003To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5073); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCall1004To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5074); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCall1006To1002(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5075); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCall1007To1002(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5076); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCallsAccount1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results
|
||||
var reply *engine.Account
|
||||
attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() == 10.0 { // Make sure we debitted
|
||||
t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
|
||||
} else if reply.Disabled == true {
|
||||
t.Error("Account disabled")
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "67" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnDerived: true}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].ReqType != utils.META_RATED {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Subject != "1002" {
|
||||
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_POSTPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1001" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "61" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_PSEUDOPREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1001" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "63" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_RATED {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1001" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "62" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "64" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "66" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCallsAccountFraud1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply string
|
||||
attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out", Value: 101}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
|
||||
} else if reply != "OK" {
|
||||
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
|
||||
}
|
||||
}
|
||||
|
||||
// Based on Fraud automatic mitigation, our account should be disabled
|
||||
func TestTutOsipsCallsAccountDisabled1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply *engine.Account
|
||||
attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.Disabled == false {
|
||||
t.Error("Account should be disabled per fraud detection rules.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsStopPjsuaListener(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
|
||||
tutOsipsCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua
|
||||
time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsStopCgrEngine(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.KillEngine(100); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsStopOpensips(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
engine.KillProcName("opensips", 100)
|
||||
}
|
||||
Reference in New Issue
Block a user