Renamed tutorials_test to tutorial_tests

This commit is contained in:
Tripon Alexandru-Ionut
2019-06-13 09:48:59 +03:00
committed by Dan Christian Bogos
parent d3d9769034
commit 1ec879deab
36 changed files with 14 additions and 14 deletions

View File

@@ -0,0 +1,15 @@
The included Asterisk configuration files are intended to be an example
implementation for a fictitious company, Super Awesome Company.
It can serve as a handy reference for understanding a simple Asterisk
configuration in an approximate real-world environment.
If you intend to use this configuration as a template for your own, then
you will need to change many values in the various configuration files to
match your own devices, network, SIP ITSP accounts and more.
For further documentation on this configuration see the Asterisk wiki:
https://wiki.asterisk.org/wiki/display/AST/Reference+Use+Cases+for+Asterisk.
Please report bugs or errors in configuration on the Asterisk issue tracker:
https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines

View File

@@ -0,0 +1,8 @@
[general]
enabled = yes
allowed_origins = http://cgrates.org
[cgrates]
type = user
read_only = no
password = CGRateS.org

View File

@@ -0,0 +1,12 @@
[directories]
astetcdir => /usr/share/cgrates/tutorial_tests/asterisk_ari/asterisk/etc/asterisk
astspooldir => /tmp/cgr_asterisk_ari/asterisk/spool
astlogdir => /tmp/cgr_asterisk_ari/asterisk/log
astrundir => /tmp/cgr_asterisk_ari/asterisk/run
astdbdir => /tmp/cgr_asterisk_ari/asterisk/lib
[options]
runuser = asterisk ; The user to run as. The default is root.
rungroup = asterisk ; The group to run as. The default is root

View File

@@ -0,0 +1,7 @@
[general]
enable=yes
[custom]
; We log the unique ID as it can be useful for troubleshooting any issues
; that arise.
loguniqueid=yes

View File

@@ -0,0 +1,4 @@
[mappings]
; Our CDR log will be written to /var/log/asterisk/cdr-custom/Master.csv
; with the following schema.
Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)}

View File

@@ -0,0 +1 @@
; All conferences use default settings. This config must be present to load the confbridge application

View File

@@ -0,0 +1,8 @@
[internal]
exten => _1XXX,1,NoOp()
same => n,Set(CGRMaxSessionTime=0); use it to disconnect automatically the call if CGRateS is not active
same => n,DumpChan()
same => n,Stasis(cgrates_auth,cgr_reqtype=*prepaid,cgr_supplier=supplier1,cgr_subsystems=*accounts*attributes*resources*stats*suppliers*thresholds)
same => n,Dial(PJSIP/${EXTEN},30,L(${CGRMaxSessionTime}))
same => n,Hangup()

View File

@@ -0,0 +1,4 @@
[general]
enabled = yes
bindaddr = 0.0.0.0
bindport = 8088

View File

@@ -0,0 +1,19 @@
[general]
country = us ; We are in Waldo, Al, USA so the US is our default.
[us]
description = United States / North America
ringcadence = 2000,4000
dial = 350+440
busy = 480+620/500,0/500
ring = 440+480/2000,0/4000
congestion = 480+620/250,0/250
callwaiting = 440/300,0/10000
dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
record = 1400/500,0/15000
info = !950/330,!1400/330,!1800/330,0
stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
; Additional country configurations can be found in the Asterisk source
; at /configs/samples/indications.conf.sample

View File

@@ -0,0 +1,9 @@
[general]
[logfiles]
console = verbose,notice,warning,error
;messages = notice,warning,error
;full = verbose,notice,warning,error,debug
;security = security

View File

@@ -0,0 +1,155 @@
;
; AMI - The Asterisk Manager Interface
;
; Third party application call management support and PBX event supervision
;
; Use the "manager show commands" at the CLI to list available manager commands
; and their authorization levels.
;
; "manager show command <command>" will show a help text.
;
; ---------------------------- SECURITY NOTE -------------------------------
; Note that you should not enable the AMI on a public IP address. If needed,
; block this TCP port with iptables (or another FW software) and reach it
; with IPsec, SSH, or SSL vpn tunnel. You can also make the manager
; interface available over http/https if Asterisk's http server is enabled in
; http.conf and if both "enabled" and "webenabled" are set to yes in
; this file. Both default to no. httptimeout provides the maximum
; timeout in seconds before a web based session is discarded. The
; default is 60 seconds.
;
[general]
enabled = yes
;webenabled = yes
port = 5038
bindaddr = 0.0.0.0
; Parameters that control AMI over TLS. ("enabled" must be set too).
; You can open a connection to this socket with e.g.
;
; openssl s_client -connect my_host:5039
;
;tlsenable=no ; set to YES to enable it
;tlsbindaddr=0.0.0.0:5039 ; address and port to bind to, default to bindaddr and port 5039
;tlscertfile=/tmp/asterisk.pem ; path to the certificate.
;tlsprivatekey=/tmp/private.pem ; path to the private key, if no private given,
; if no tlsprivatekey is given, default is to search
; tlscertfile for private key.
;tlscipher=<cipher string> ; string specifying which SSL ciphers to use or not use
;
;allowmultiplelogin = yes ; IF set to no, rejects manager logins that are already in use.
; ; The default is yes.
;
;displayconnects = yes
;
; Add a Unix epoch timestamp to events (not action responses)
;
;timestampevents = yes
;brokeneventsaction = yes ; Restore previous behavior that caused the events
; action to not return a response in certain
; circumstances. Defaults to 'no'.
;
; Display certain channel variables every time a channel-oriented
; event is emitted:
;
;channelvars = var1,var2,var3
; debug = on ; enable some debugging info in AMI messages (default off).
; Also accessible through the "manager debug" CLI command.
; authtimeout specifies the maximum number of seconds a client has to
; authenticate. If the client does not authenticate beofre this timeout
; expires, the client will be disconnected. (default: 30 seconds)
;authtimeout = 30
; authlimit specifies the maximum number of unauthenticated sessions that will
; be allowed to connect at any given time.
;authlimit = 50
;httptimeout = 60
; a) httptimeout sets the Max-Age of the http cookie
; b) httptimeout is the amount of time the webserver waits
; on a action=waitevent request (actually its httptimeout-10)
; c) httptimeout is also the amount of time the webserver keeps
; a http session alive after completing a successful action
;[mark]
;secret = mysecret
;deny=0.0.0.0/0.0.0.0
;permit=209.16.236.73/255.255.255.0
;acl=named_acl_example ; use a named ACL from acl.conf
;
;
;setvar=PBXACCOUNT=edvina
; The setvar option defines channel variables that will be set when this account
; originates a call. You can define multiple setvar= commands for one manager
; user.
;
;eventfilter=Event: Newchannel
;eventfilter=Channel: (PJ)?SIP/(james|jim|john)-
;eventfilter=!Channel: DAHDI/
; The eventfilter option is used to whitelist or blacklist events per user.
; A filter consists of an (unanchored) regular expression that is run on the
; entire event data. If the first character of the filter is an exclamation
; mark (!), the filter is appended to the blacklist instead of the whitelist.
; After first checking the read access below, the regular expression filters
; are processed as follows:
; - If no filters are configured all events are reported as normal.
; - If there are white filters only: implied black all filter processed first,
; then white filters.
; - If there are black filters only: implied white all filter processed first,
; then black filters.
; - If there are both white and black filters: implied black all filter processed
; first, then white filters, and lastly black filters.
;
; If the device connected via this user accepts input slowly,
; the timeout for writes to it can be increased to keep it
; from being disconnected (value is in milliseconds)
;
; writetimeout = 100
;
;displayconnects = yes ; Display on CLI user login/logoff
;
; Authorization for various classes
;
; Read authorization permits you to receive asynchronous events, in general.
; Write authorization permits you to send commands and get back responses. The
; following classes exist:
;
; all - All event classes below (including any we may have missed).
; system - General information about the system and ability to run system
; management commands, such as Shutdown, Restart, and Reload.
; call - Information about channels and ability to set information in a
; running channel.
; log - Logging information. Read-only. (Defined but not yet used.)
; verbose - Verbose information. Read-only. (Defined but not yet used.)
; agent - Information about queues and agents and ability to add queue
; members to a queue.
; user - Permission to send and receive UserEvent.
; config - Ability to read and write configuration files.
; command - Permission to run CLI commands. Write-only.
; dtmf - Receive DTMF events. Read-only.
; reporting - Ability to get information about the system.
; cdr - Output of cdr_manager, if loaded. Read-only.
; dialplan - Receive NewExten and VarSet events. Read-only.
; originate - Permission to originate new calls. Write-only.
; agi - Output AGI commands executed. Input AGI command to execute.
; cc - Call Completion events. Read-only.
; aoc - Permission to send Advice Of Charge messages and receive Advice
; - Of Charge events.
; test - Ability to read TestEvent notifications sent to the Asterisk Test
; Suite. Note that this is only enabled when the TEST_FRAMEWORK
; compiler flag is defined.
; security - Security Events. Read-only.
; message - Permissions to send out of call messages. Write-only
;
;read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
;write = system,call,agent,user,config,command,reporting,originate,message

View File

@@ -0,0 +1,136 @@
[modules]
autoload = no
; This is a minimal module load. We are loading only the modules required for
; the Asterisk features used in the Super Awesome Company configuration.
; Applications
load = app_bridgewait.so
load = app_dial.so
load = app_playback.so
load = app_stack.so
load = app_verbose.so
load = app_voicemail.so
load = app_directory.so
load = app_confbridge.so
load = app_queue.so
load = app_dumpchan.so
; Bridging
load = bridge_builtin_features.so
load = bridge_builtin_interval_features.so
load = bridge_holding.so
load = bridge_native_rtp.so
load = bridge_simple.so
load = bridge_softmix.so
; Call Detail Records
load = cdr_custom.so
; Channel Drivers
load = chan_bridge_media.so
load = chan_pjsip.so
; Codecs
load = codec_gsm.so
load = codec_resample.so
load = codec_ulaw.so
load = codec_g722.so
; Formats
load = format_gsm.so
load = format_pcm.so
load = format_wav_gsm.so
load = format_wav.so
; Functions
load = func_callerid.so
load = func_cdr.so
load = func_pjsip_endpoint.so
load = func_sorcery.so
load = func_devstate.so
load = func_strings.so
; Core/PBX
load = pbx_config.so
; Resources
load = res_musiconhold.so
load = res_pjproject.so
load = res_pjsip_acl.so
load = res_pjsip_authenticator_digest.so
load = res_pjsip_caller_id.so
load = res_pjsip_dialog_info_body_generator.so
load = res_pjsip_diversion.so
load = res_pjsip_dtmf_info.so
load = res_pjsip_endpoint_identifier_anonymous.so
load = res_pjsip_endpoint_identifier_ip.so
load = res_pjsip_endpoint_identifier_user.so
load = res_pjsip_exten_state.so
load = res_pjsip_header_funcs.so
load = res_pjsip_logger.so
load = res_pjsip_messaging.so
load = res_pjsip_multihomed.so
load = res_pjsip_mwi_body_generator.so
load = res_pjsip_mwi.so
load = res_pjsip_nat.so
load = res_pjsip_notify.so
load = res_pjsip_one_touch_record_info.so
load = res_pjsip_outbound_authenticator_digest.so
load = res_pjsip_outbound_publish.so
load = res_pjsip_outbound_registration.so
load = res_pjsip_path.so
load = res_pjsip_pidf_body_generator.so
load = res_pjsip_pidf_digium_body_supplement.so
load = res_pjsip_pidf_eyebeam_body_supplement.so
load = res_pjsip_publish_asterisk.so
load = res_pjsip_pubsub.so
load = res_pjsip_refer.so
load = res_pjsip_registrar_expire.so
load = res_pjsip_registrar.so
load = res_pjsip_rfc3326.so
load = res_pjsip_sdp_rtp.so
load = res_pjsip_send_to_voicemail.so
load = res_pjsip_session.so
load = res_pjsip.so
load = res_pjsip_t38.so
load = res_pjsip_transport_websocket.so
load = res_pjsip_xpidf_body_generator.so
load = res_rtp_asterisk.so
load = res_sorcery_astdb.so
load = res_sorcery_config.so
load = res_sorcery_memory.so
load = res_sorcery_realtime.so
load = res_timing_timerfd.so
;ARI
load => app_stasis.so
load => res_http_websocket.so
load => res_stasis.so
load => res_stasis_answer.so
load => res_stasis_device_state.so
load => res_stasis_playback.so
load => res_stasis_recording.so
load => res_stasis_snoop.so
load => res_ari.so
load => res_ari_applications.so
load => res_ari_asterisk.so
load => res_ari_bridges.so
load => res_ari_channels.so
load => res_ari_device_states.so
load => res_ari_endpoints.so
load => res_ari_events.so
load => res_ari_mailboxes.so
load => res_ari_model.so
load => res_ari_playbacks.so
load => res_ari_recordings.so
load => res_ari_sounds.so

View File

@@ -0,0 +1,5 @@
[general]
[default]
mode = files
directory = moh

View File

@@ -0,0 +1,147 @@
[testcalls]
type=transport
protocol=udp
bind=0.0.0.0:5080
[1001]
type = endpoint
transport = testcalls
context = internal
disallow = all
allow = ulaw
allow = alaw
aors = 1001
auth = 1001
[1001]
type = aor
max_contacts = 5
[1001]
type=auth
auth_type=userpass
username=1001
password=CGRateS.org
[1002]
type = endpoint
transport = testcalls
context = internal
disallow = all
allow = ulaw
allow = alaw
aors = 1002
auth = 1002
[1002]
type = aor
max_contacts = 5
qualify_frequency = 0
[1002]
type=auth
auth_type=userpass
username=1002
password=CGRateS.org
[1003]
type = endpoint
transport = testcalls
context = internal
aors = 1003
auth = 1003
disallow = all
allow = ulaw
allow = alaw
[1003]
type = aor
max_contacts = 5
[1003]
type=auth
auth_type=userpass
username=1003
password=CGRateS.org
[1004]
type = endpoint
transport = testcalls
context = internal
aors = 1004
auth = 1004
disallow = all
allow = ulaw
allow = alaw
[1004]
type = aor
max_contacts = 5
[1004]
type=auth
auth_type=userpass
username=1004
password=CGRateS.org
[1005]
type = endpoint
transport = testcalls
context = internal
aors = 1005
auth = 1005
disallow = all
allow = ulaw
allow = alaw
[1005]
type = aor
max_contacts = 5
[1005]
type=auth
auth_type=userpass
username=1005
password=CGRateS.org
[1006]
type = endpoint
transport = testcalls
context = internal
aors = 1006
auth = 1006
disallow = all
allow = ulaw
allow = alaw
[1006]
type = aor
max_contacts = 5
[1006]
type=auth
auth_type=userpass
username=1006
password=CGRateS.org
[1007]
type = endpoint
transport = testcalls
context = internal
aors = 1007
auth = 1007
disallow = all
allow = ulaw
allow = alaw
[1007]
type = aor
max_contacts = 5
[1007]
type=auth
auth_type=userpass
username=1007
password=CGRateS.org

View File

@@ -0,0 +1,19 @@
[general]
monitor-type = MixMonitor
;========================Sales Queue ==
; Calls all sales persons in a ring-all fashion
[sales]
strategy=ringall
member => PJSIP/1109 ; Terry Jules - Director of Sales
member => PJSIP/1105 ; Garnet Claude - Sales Associate
member => PJSIP/1112 ; Franny Ocean - Sales Associate
;===================== Customer Advocate Queue ==
; Calls all customer advocates in a ring-all fashion
[customer_advocate]
strategy=ringall
member => PJSIP/1101 ; Maria Berny - Director of Customer Experience
member => PJSIP/1115 ; Dusty Williams - Customer Advocate
member => PJSIP/1102 ; Tommy Briar - Customer Advocate

View File

@@ -0,0 +1,23 @@
[general]
format = wav49|gsm|wav
[default]
[example]
; Voicemail context for all internal users in the example.com domain.
1101 = 0717,Maria Berny
1102 = 7085,Tommie Briar
1103 = 1809,Penelope Bronte
1104 = 0039,Richard Casey
1105 = 6618,Garnet Claude
1106 = 9805,Aaron Courtney
1107 = 7484,Lindsey Freddie
1108 = 7788,Colby Hildred
1109 = 5750,Terry Jules
1110 = 3702,Hollis Justy
1111 = 1878,Temple Morgan
1112 = 5497,Franny Ocean
1113 = 1637,Laverne Roberts
1114 = 3717,Sal Smith
1115 = 3088,Dusty Williams

View File

@@ -0,0 +1,175 @@
#! /bin/sh
# $Id$
#
# Mon Jun 04 2007 Iñaki Baz Castillo <ibc@in.ilimit.es>
# - Eliminated SAFE_ASTERISK since it doesn't work as LSB script (it could require a independent "safe_asterisk" init script).
# - Load and use the standar "/lib/lsb/init-functions".
# - Added "--oknodo" to "start-stop-daemon" for compatibility with LSB:
# http://www.linux-foundation.org/spec/refspecs/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
#
# Thu Nov 17 2005 Gregory Boehnlein <damin@nacs.net>
# - Reversed behavior of LD_ASSUME_KERNEL=2.4.1
# - Added detailed failure messages
#
# Sun Jul 18 2004 Gregory Boehnlein <damin@nacs.net>
# - Added test for safe_asterisk
# - Changed "stop gracefully" to "stop now"
# - Added support for -U and -G command line options
# - Modified "reload" to call asterisk -rx 'reload'
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=asterisk
DESC="Asterisk PBX"
TUTDIR=/usr/share/cgrates/tutorial_tests/asterisk_ari/asterisk
TMP_DIR=/tmp/cgr_asterisk_ari/asterisk
# Full path to asterisk binary
DAEMON=/usr/sbin/asterisk
ASTVARRUNDIR=$TMP_DIR/run
LOGDIR=$TMP_DIR/log
DBDIR=$TMP_DIR/lib
CDRDIR=$LOGDIR/cdr-custom
SPOOLDIR=$TMP_DIR/spool
ALTCONF=$TUTDIR/etc/asterisk/asterisk.conf
TRUE=/bin/true
AST_USER="asterisk"
AST_GROUP="asterisk"
VERBOSITY=1
### BEGIN INIT INFO
# Provides: asterisk
# Required-Start: $network $syslog $named $local_fs $remote_fs
# Required-Stop: $network $syslog $named $local_fs $remote_fs
# Should-Start: dahdi misdn lcr wanrouter mysql postgresql
# Should-Stop: dahdi misdn lcr wanrouter mysql postgresql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Asterisk PBX
# Description: the Asterisk Open Source PBX
### END INIT INFO
set -e
if ! [ -x $DAEMON ] ; then
echo "ERROR: $DAEMON not found"
exit 0
fi
if ! [ -d $ASTETCDIR ] ; then
echo "ERROR: $ASTETCDIR directory not found"
exit 0
fi
if [ ! -d $LOGDIR ]; then
mkdir -p $LOGDIR
chown -R $AST_USER:$AST_GROUP $LOGDIR
fi
if [ ! -d $CDRDIR ]; then
mkdir -p $CDRDIR
chown -R $AST_USER:$AST_GROUP $CDRDIR
fi
if [ ! -d $SPOOLDIR ]; then
mkdir -p $SPOOLDIR
chown -R $AST_USER:$AST_GROUP $SPOOLDIR
fi
if [ ! -d $DBDIR ]; then
mkdir -p $DBDIR
chown -R $AST_USER:$AST_GROUP $DBDIR
fi
# Use the LSB standard functions for services management
. /lib/lsb/init-functions
# Allow configuration overrides in /etc/default/asterisk
CONFIG0=`readlink $0 || :` # readlink returns 1 when something isn't a symlink
if [ "$CONFIG0" = "" ]; then
CONFIGFILE=/etc/default/`basename $0`
else
CONFIGFILE=/etc/default/`basename $CONFIG0`
fi
[ -r $CONFIGFILE ] && . $CONFIGFILE
case "$1" in
start)
# Check if Asterisk is already running. If it is, then bug out, because
# starting up Asterisk when Asterisk is already running is very bad.
VERSION=`${DAEMON} -rx 'core show version' 2>/dev/null || ${TRUE}`
if [ "`echo $VERSION | cut -c 1-8`" = "Asterisk" ]; then
echo "Asterisk is already running. $0 will exit now."
exit 0
fi
log_begin_msg "Starting $DESC: $NAME"
if [ ! -d $ASTVARRUNDIR ]; then
mkdir -p $ASTVARRUNDIR
fi
if [ $AST_USER ] ; then
ASTARGS="$ASTARGS -U $AST_USER"
chown $AST_USER $ASTVARRUNDIR
fi
if [ $AST_GROUP ] ; then
ASTARGS="$ASTARGS -G $AST_GROUP"
chgrp $AST_GROUP $ASTVARRUNDIR
fi
if [ $ALTCONF ]; then
ASTARGS="$ASTARGS -C $ALTCONF"
fi
if [ "x$COREDUMP" = "xyes" ]; then
ASTARGS="$ASTARGS -g"
fi
if [ "0$MAXLOAD" -gt "0" ]; then
ASTARGS="$ASTARGS -L $MAXLOAD"
fi
if [ "0$MAXCALLS" -gt "0" ]; then
ASTARGS="$ASTARGS -M $MAXCALLS"
fi
if [ "0$VERBOSITY" -gt "0" ]; then
for i in `seq 1 $VERBOSITY`; do
ASTARGS="$ASTARGS -v"
done
# -v implies -f, so we override that implicit specification here
ASTARGS="$ASTARGS -F"
fi
if [ "x$INTERNALTIMING" = "xyes" ]; then
ASTARGS="$ASTARGS -I"
fi
if [ "x$TEMPRECORDINGLOCATION" = "xyes" -o "x$TMPRECORDINGLOCATION" = "xyes" ]; then
ASTARGS="$ASTARGS -t"
fi
if test "x$COLOR" = "xno" ; then
ASTARGS="$ASTARGS -n"
fi
# "start-stop-daemon --oknodo" returns 0 even if Asterisk was already running (as LSB expects):
echo "$DAEMON -- $ASTARGS"
start-stop-daemon --start --oknodo --exec $DAEMON -- $ASTARGS
log_end_msg $?
;;
stop)
log_begin_msg "Stopping $DESC: $NAME"
# "start-stop-daemon --oknodo" returns 0 even if Asterisk was already stopped (as LSB expects):
start-stop-daemon --stop --oknodo --exec $DAEMON
log_end_msg $?
;;
reload)
echo "Reloading $DESC configuration files."
$DAEMON -rx 'module reload' > /dev/null 2> /dev/null
;;
restart|force-reload)
$0 stop
sleep 2 # It needs some time to really be stopped.
$0 start
# "restart|force-reload" starts Asterisk and returns 0 even if Asterisk was stopped (as LSB expects).
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,145 @@
{
// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
// Copyright (C) ITsysCOM GmbH
"general": {
"log_level": 7,
"node_id":"CGRAsterisk",
"reply_timeout": "5s",
},
"listen": {
"rpc_json": ":2012",
"rpc_gob": ":2013",
"http": ":2080",
},
"stor_db": {
"db_password": "CGRateS.org",
},
"scheduler": {
"enabled": true,
},
"rals": {
"enabled": true,
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
},
"cdrs": {
"enabled": true,
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"chargers_conns": [
{"address": "*internal"}
],
"sessions_cost_retries": 5,
},
"chargers": {
"enabled": true,
"attributes_conns": [
{"address": "*internal"}
],
},
"sessions": {
"enabled": true,
"rals_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"cdrs_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"resources_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"suppliers_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"attributes_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"chargers_conns": [
{"address": "*internal"}
],
"store_session_costs": true,
"debit_interval": "5s",
"channel_sync_interval":"7s",
},
"asterisk_agent": {
"enabled": true,
"asterisk_conns":[
{"address": "127.0.0.1:8088", "user": "cgrates",
"password": "CGRateS.org", "connect_attempts": 3,"reconnects": 10}
],
"sessions_conns": [
{"address": "*internal"},
],
"create_cdr": true,
},
"attributes": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"resources": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"stats": {
"enabled": true,
"string_indexed_fields": ["Account","RunID","Destination"],
},
"thresholds": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"suppliers": {
"enabled": true,
"rals_conns": [
{"address": "*internal"},
],
"resources_conns": [
{"address": "*internal"},
],
"stats_conns": [
{"address": "*internal"},
],
"string_indexed_fields": ["Account"],
},
}

View File

@@ -0,0 +1,184 @@
#! /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
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="CGRateS real-time online/offline Charging System"
NAME=cgrates
DAEMON=/usr/bin/cgr-engine
USER=cgrates
GROUP=cgrates
DAEMON_OPTS=""
TUTFOLDER=/usr/share/cgrates/tutorial_tests/asterisk_ari/cgrates
TMP_DIR=/tmp/cgr_astevents/cgrates
SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME
RUNDIR=$TMP_DIR/run
PIDFILE=$RUNDIR/cgr-engine.pid
STACKTRACE=$RUNDIR/$NAME.strace
ENABLE=true
DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates"
CDREDIR=$TMP_DIR/cdre
CDRCINDIR=$TMP_DIR/cdrc/in
CDRCOUTDIR=$TMP_DIR/cdrc/out
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# 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
touch $STACKTRACE
chown -R $USER:$GROUP $RUNDIR
fi
# Install the cdrc folder
if [ ! -d $CDRCINDIR ]; then
mkdir -p $CDRCINDIR
chown $USER:$GROUP $CDRCINDIR
mkdir -p $CDRCOUTDIR
chown $USER:$GROUP $CDRCOUTDIR
fi
# Install the cdre folder
if [ ! -d $CDREDIR ]; then
mkdir -p $CDREDIR
chown $USER:$GROUP $CDREDIR
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
echo "\n### Started at:" `date`>>$STACKTRACE
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\
|| return 1
start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\
--startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \
|| 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
:

View File

@@ -0,0 +1,17 @@
Tutorial FS_JSON
================
Scenario:
---------
- FreeSWITCH with minimal custom configuration.
- Added following users (with configs in *etc/freeswitch/directory/default*): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1006-prepaid, 1007-prepaid.
- Have added inside default dialplan CGR own extensions just before routing towards users (*etc/freeswitch/dialplan/default.xml*).
- **CGRateS** with following components:
- CGR-SM started as prepaid controller, with debits taking place at 5s intervals.
- CGR-Mediator component attaching costs to the raw CDRs from FreeSWITCH_ inside CGR StorDB.
- CGR-CDRE exporting mediated CDRs from CGR StorDB (export path: */tmp*).
- CGR-CDRStats component building up stats in 5 different queues.

View File

@@ -0,0 +1,142 @@
{
// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
// Copyright (C) ITsysCOM GmbH
"general": {
"log_level": 7,
"node_id":"CGRFreeswitch",
},
"listen": {
"rpc_json": ":2012",
"rpc_gob": ":2013",
"http": ":2080",
},
"stor_db": {
"db_password": "CGRateS.org",
},
"scheduler": {
"enabled": true,
},
"rals": {
"enabled": true,
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
},
"cdrs": {
"enabled": true,
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"chargers_conns": [
{"address": "*internal"}
],
"sessions_cost_retries": 5,
},
"chargers": {
"enabled": true,
"attributes_conns": [
{"address": "*internal"}
],
},
"sessions": {
"enabled": true,
"rals_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"cdrs_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"resources_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"suppliers_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"attributes_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"chargers_conns": [
{"address": "*internal"}
],
"store_session_costs": true,
"debit_interval": "5s",
"channel_sync_interval":"7s",
},
"freeswitch_agent": {
"enabled": true,
"event_socket_conns":[
{"address": "127.0.0.1:8021", "password": "ClueCon", "reconnects": -1,"alias":""}
],
"sessions_conns": [
{"address": "*internal"},
],
},
"attributes": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"resources": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"stats": {
"enabled": true,
"string_indexed_fields": ["Account","RunID","Destination"],
},
"thresholds": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"suppliers": {
"enabled": true,
"rals_conns": [
{"address": "*internal"},
],
"resources_conns": [
{"address": "*internal"},
],
"stats_conns": [
{"address": "*internal"},
],
"string_indexed_fields": ["Account"],
},
}

View File

@@ -0,0 +1,184 @@
#! /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
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="CGRateS real-time charging system"
NAME=cgrates
DAEMON=/usr/bin/cgr-engine
USER=cgrates
GROUP=cgrates
DAEMON_OPTS=""
TUTFOLDER=/usr/share/cgrates/tutorial_tests/fs_evsock/cgrates
TMP_DIR=/tmp/cgr_fsevsock/cgrates
SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME
RUNDIR=$TMP_DIR/run
PIDFILE=$RUNDIR/cgr-engine.pid
STACKTRACE=$RUNDIR/$NAME.strace
ENABLE=true
DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates"
CDREDIR=$TMP_DIR/cdre
CDRCINDIR=$TMP_DIR/cdrc/in
CDRCOUTDIR=$TMP_DIR/cdrc/out
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# 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
touch $STACKTRACE
chown -R $USER:$GROUP $RUNDIR
fi
# Install the cdrc folder
if [ ! -d $CDRCINDIR ]; then
mkdir -p $CDRCINDIR
chown $USER:$GROUP $CDRCINDIR
mkdir -p $CDRCOUTDIR
chown $USER:$GROUP $CDRCOUTDIR
fi
# Install the cdre folder
if [ ! -d $CDREDIR ]; then
mkdir -p $CDREDIR
chown $USER:$GROUP $CDREDIR
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
echo "\n### Started at:" `date`>>$STACKTRACE
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\
|| return 1
start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\
--startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \
|| 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
:

View File

@@ -0,0 +1,145 @@
#!/bin/sh
### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*-
### BEGIN INIT INFO
# Provides: freeswitch
# Required-Start: $network $remote_fs $local_fs
# Required-Stop: $network $remote_fs $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: FreeSWITCH Softswitch
# Description: FreeSWITCH Softswitch
### END INIT INFO
# Author: Travis Cross <tc@traviscross.com>
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=freeswitch
NAME=freeswitch
DAEMON=/usr/bin/freeswitch
USER=freeswitch
GROUP=freeswitch
TUTDIR=/usr/share/cgrates/tutorial_tests/fs_evsock/freeswitch
SCRIPTNAME=$TUTDIR/etc/init.d/$NAME
TMP_DIR=/tmp/cgr_fsevsock/freeswitch
CONFDIR=$TUTDIR/etc/$NAME
RUNDIR=$TMP_DIR/run
LOGDIR=$TMP_DIR/log
PIDFILE=$RUNDIR/$NAME.pid
WORKDIR=$TMP_DIR/lib
DBDIR=$WORKDIR/db/
DAEMON_ARGS="-rp -conf $CONFDIR -db $DBDIR -log $LOGDIR -u $USER -g $GROUP -nonat -nc"
[ -x $DAEMON ] || exit 0
. /lib/init/vars.sh
. /lib/lsb/init-functions
if [ ! -d $RUNDIR ]; then
mkdir -p $RUNDIR
chown -R $USER:$GROUP $RUNDIR
chmod -R ug=rwX,o= $RUNDIR
fi
if [ ! -d $LOGDIR ]; then
mkdir -p $LOGDIR
chown -R $USER:$GROUP $LOGDIR
fi
if [ ! -d $DBDIR ]; then
mkdir -p $DBDIR
chown -R $USER:$GROUP $DBDIR
fi
do_start() {
if ! [ -f $CONFDIR/freeswitch.xml ]; then
echo "$NAME is not configured so not starting.">&2
echo "Please review /usr/share/doc/$NAME/README.Debian">&2
return 3
fi
echo $DAEMON_ARGS
start-stop-daemon --start --quiet \
--pidfile $PIDFILE --exec $DAEMON --name $NAME --user $USER \
--test > /dev/null \
|| return 1
ulimit -s 240
start-stop-daemon --start --quiet \
--pidfile $PIDFILE --exec $DAEMON --name $NAME --user $USER \
--chdir $WORKDIR -- $DAEMON_ARGS $DAEMON_OPTS \
|| return 2
return 0
}
stop_fs() {
start-stop-daemon --stop --quiet \
--pidfile $PIDFILE --name $NAME --user $USER \
--retry=TERM/30/KILL/5
}
stop_fs_children() {
start-stop-daemon --stop --quiet \
--exec $DAEMON \
--oknodo --retry=0/30/KILL/5
}
do_stop() {
stop_fs
RETVAL="$?"
[ "$RETVAL" -eq 2 ] && return 2
stop_fs_children
[ "$?" -eq 2 ] && return 2
rm -f $PIDFILE
return "$RETVAL"
}
do_reload() {
start-stop-daemon --stop --quiet \
--pidfile $PIDFILE --name $NAME --user $USER \
--signal HUP
}
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)
log_daemon_msg "Reloading $DESC" "$NAME"
do_reload
log_end_msg $?
;;
restart)
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 ;;
esac
;;
*) log_end_msg 1 ;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
exit 0

View File

@@ -0,0 +1,141 @@
{
// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
// Copyright (C) ITsysCOM GmbH
"general": {
"log_level": 7,
"node_id":"CGRKamailio",
"reply_timeout": "5s",
},
"listen": {
"rpc_json": ":2012",
"rpc_gob": ":2013",
"http": ":2080",
},
"stor_db": {
"db_password": "CGRateS.org",
},
"scheduler": {
"enabled": true,
},
"rals": {
"enabled": true,
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
},
"cdrs": {
"enabled": true,
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"sessions_cost_retries": 5,
},
"chargers": {
"enabled": true,
"attributes_conns": [
{"address": "*internal"}
],
},
"sessions": {
"enabled": true,
"rals_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"cdrs_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"resources_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"suppliers_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"attributes_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"chargers_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"},
],
"store_session_costs": true,
"debit_interval": "5s",
"channel_sync_interval":"7s",
},
"kamailio_agent": {
"enabled": true,
"evapi_conns":[
{"address": "127.0.0.1:8448", "reconnects": 5}
],
"sessions_conns": [
{"address": "*internal"},
],
"create_cdr": true,
},
"attributes": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"resources": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"stats": {
"enabled": true,
"string_indexed_fields": ["Account","RunID","Destination"],
},
"thresholds": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"suppliers": {
"enabled": true,
"rals_conns": [
{"address": "*internal"},
],
"resources_conns": [
{"address": "*internal"},
],
"stats_conns": [
{"address": "*internal"},
],
"string_indexed_fields": ["Account"],
},
}

View File

@@ -0,0 +1,175 @@
#! /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
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="CGRateS real-time charging system"
NAME=cgrates
DAEMON=/usr/bin/cgr-engine
USER=cgrates
GROUP=cgrates
DAEMON_OPTS=""
TUTFOLDER=/usr/share/cgrates/tutorial_tests/kamevapi/cgrates
TMP_DIR=/tmp/cgr_kamevapi/cgrates
SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME
RUNDIR=$TMP_DIR/run
PIDFILE=$RUNDIR/cgr-engine.pid
STACKTRACE=$RUNDIR/$NAME.strace
ENABLE=true
DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates"
CDREDIR=$TMP_DIR/cdre
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# 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
touch $STACKTRACE
chown -R $USER:$GROUP $RUNDIR
fi
# Install the cdre folder
if [ ! -d $CDREDIR ]; then
mkdir -p $CDREDIR
chown -R $USER:$GROUP $CDREDIR
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
echo "\n### Started at:" `date`>>$STACKTRACE
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\
|| return 1
start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\
--startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \
|| 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
:

View File

@@ -0,0 +1,166 @@
#! /bin/sh
#
### BEGIN INIT INFO
# Provides: kamailio
# Required-Start: $syslog $network $local_fs $remote_fs $time
# Should-Start: $named slapd mysql postgresql snmpd radiusd
# Should-Stop: $named slapd mysql postgresql snmpd radiusd
# Required-Stop: $syslog $network $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start the Kamailio SIP proxy server
# Description: Start the Kamailio SIP proxy server
### END INIT INFO
. /lib/lsb/init-functions
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/kamailio
NAME=kamailio
DESC="Kamailio SIP Server"
TUTDIR=/usr/share/cgrates/tutorial_tests/kamevapi/
TMP_DIR=/tmp/cgr_kamevapi/kamailio
HOMEDIR=$TMP_DIR/run/
PIDFILE=$HOMEDIR/$NAME.pid
CFGFILE=$TUTDIR/kamailio/etc/kamailio/kamailio.cfg
USER=kamailio
GROUP=kamailio
# Amount of shared and private memory to allocate
# for the running Kamailio server (in Mb)
SHM_MEMORY=64
PKG_MEMORY=8
DUMP_CORE=no
if [ ! -d $HOMEDIR ]; then
mkdir -p $HOMEDIR
chown -R $USER:$GROUP $HOMEDIR
chmod -R ug=rwX,o= $HOMEDIR
fi
if [ ! -d $LOGDIR ]; then
mkdir -p $LOGDIR
chown -R $USER:$GROUP $LOGDIR
fi
# Do not start kamailio 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
log_failure_msg "Not starting $DESC: fork=no specified in config file; run /etc/init.d/kamailio debug instead"
exit 0
fi
}
check_kamailio_config ()
{
# Check if kamailio configuration is valid before starting the server
set +e
out=$($DAEMON -f $CFGFILE -M $PKG_MEMORY -c 2>&1 > /dev/null)
retcode=$?
set -e
if [ "$retcode" != '0' ]; then
log_failure_msg "Not starting $DESC: invalid configuration file!"
log_failure_msg
log_failure_msg "$out"
log_failure_msg
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 kamailio 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 kamailio and cannot
# write to the file. If the file exists before kamailio starts, it
# won't change it's ownership and will be writable for both root
# and kamailio, no matter what options are chosen at install time
RADIUS_SEQ_FILE=/var/run/kamailio/kamailio_radius.seq
if [ -d /var/run/kamailio ]; then
chown ${USER}:${GROUP} /var/run/kamailio
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
set -e
SHM_MEMORY=$((`echo $SHM_MEMORY | sed -e 's/[^0-9]//g'`))
PKG_MEMORY=$((`echo $PKG_MEMORY | sed -e 's/[^0-9]//g'`))
[ -z "$USER" ] && USER=kamailio
[ -z "$GROUP" ] && GROUP=kamailio
[ $SHM_MEMORY -le 0 ] && SHM_MEMORY=64
[ $PKG_MEMORY -le 0 ] && PKG_MEMORY=4
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
# /var/run can be a tmpfs
if [ ! -d $HOMEDIR ]; then
mkdir -p $HOMEDIR
fi
OPTIONS="-f $CFGFILE -P $PIDFILE -m $SHM_MEMORY -M $PKG_MEMORY -u $USER -g $GROUP"
case "$1" in
start|debug)
check_kamailio_config
create_radius_seqfile
if [ "$1" != "debug" ]; then
check_fork
fi
log_daemon_msg "Starting $DESC: $NAME"
start-stop-daemon --start --quiet --pidfile $PIDFILE \
--exec $DAEMON -- $OPTIONS || log_failure_msg " already running"
log_end_msg 0
;;
stop)
log_daemon_msg "Stopping $DESC: $NAME"
start-stop-daemon --oknodo --stop --quiet --pidfile $PIDFILE \
--exec $DAEMON
log_end_msg 0
;;
restart|force-reload)
check_kamailio_config
create_radius_seqfile
$0 stop
sleep 1
$0 start
;;
status)
log_daemon_msg "Status of $DESC: "
status_of_proc -p"$PIDFILE" $NAME $NAME
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload|status|debug}" >&2
exit 1
;;
esac
exit 0

View File

@@ -0,0 +1,192 @@
# Kamailio-CGRateS related route blocks
# Called on new connection over evapi, should normally be the case of CGRateS engine
event_route[evapi:connection-new] {
$sht(cgrconn=>cgr) = $evapi(srcaddr) + ":" + $evapi(srcport); # Detect presence of at least one connection
}
# Called when the connection with CGRateS closes
event_route[evapi:connection-closed] {
$var(connClosed) = $evapi(srcaddr) + ":" + $evapi(srcport);
if $sht(cgrconn=>cgr) == $var(connClosed) {
$sht(cgrconn=>cgr) = $null;
}
}
# Message received from CGRateS, dispatch it to own route
event_route[evapi:message-received] {
json_get_field("$evapi(msg)", "Event", "$var(Event)");
route($(var(Event){s.rm,"})); # String characters are kept by json_get_field, remove them here
}
# Called by Kamailio on new dialog
event_route[dialog:start] {
route(CGR_CALL_START);
}
# Called by Kamailio on dialog end
event_route[dialog:end] {
route(CGR_CALL_END);
}
# Parse the CGRateS attributes from encoded variable into pseudovariables
route[PARSE_CGRATES_ATTRIBUTES] {
# convert encoded attributes into individual Kamailio pseudovariables
$var(idx) = 0;
while !strempty($(var(cgrAttributes){s.select,$var(idx),,})) {
$avp($(var(cgrAttributes){s.select,$var(idx),,}{s.select,0,:}))
= $(var(cgrAttributes){s.select,$var(idx),,}{s.select,1,:});
$var(idx) = $var(idx) + 1;
}
}
# CGRateS request for session disconnect
route[CGR_SESSION_DISCONNECT] {
json_get_field("$evapi(msg)", "HashEntry", "$var(HashEntry)");
json_get_field("$evapi(msg)", "HashId", "$var(HashId)");
json_get_field("$evapi(msg)", "Reason", "$var(Reason)");
jsonrpc_exec('{"jsonrpc":"2.0","id":1, "method":"dlg.end_dlg","params":[$(var(HashEntry){s.rm,"}),$(var(HashId){s.rm,"})]}');
}
route[CGR_DLG_LIST] {
if $sht(cgrconn=>cgr) == $null {
sl_send_reply("503","Charging controller unreachable");
exit;
}
jsonrpc_exec('{"jsonrpc":"2.0","id":1, "method":"dlg.list","params":[]}');
evapi_relay("{\"event\":\"CGR_DLG_LIST_REPLY\",
\"jsonrpl_body\":$jsonrpl(body)}");
}
# Route to mainly query account password from CGRateS
route[CGRATES_SIMPLEAUTH_REQUEST] {
if $sht(cgrconn=>cgr) == $null {
sl_send_reply("503","Charging controller unreachable");
exit;
}
evapi_async_relay("{\"event\":\"CGR_AUTH_REQUEST\",
\"tr_index\":\"$T(id_index)\",
\"tr_label\":\"$T(id_label)\",
\"cgr_subsystems\":\"*attributes\",
\"cgr_context\":\"simpleauth\",
\"reply_route\":\"CGR_SIMPLEAUTH_REPLY\",
\"Account\":\"$fU\"}");
}
# Route receiving simpleauth replies, sanitizes them and dispatch back into Kamailio inside CGRATES_SIMPLEAUTH_REPLY
route[CGR_SIMPLEAUTH_REPLY] {
json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)");
$var(TransactionIndex) = $(var(TransactionIndex){s.rm,"});
$var(id_index) = $(var(TransactionIndex){s.int});
json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
$var(TransactionLabel) = $(var(TransactionLabel){s.rm,"});
$var(id_label) = $(var(TransactionLabel){s.int});
json_get_field("$evapi(msg)", "Attributes", "$var(cgrAttributes)");
$var(cgrAttributes) = $(var(cgrAttributes){s.rm,"});
json_get_field("$evapi(msg)", "Error", "$var(cgrError)");
$var(cgrError) = $(var(cgrError){s.rm,"});
t_continue("$var(id_index)", "$var(id_label)", "CGRATES_SIMPLEAUTH_REPLY"); # Unpark the transaction
}
# Request session auth information from CGRateS
route[CGRATES_SESSIONAUTH_REQUEST] {
# Auth INVITEs with CGRateS
if $sht(cgrconn=>cgr) == $null {
sl_send_reply("503","Charging controller unreachable");
exit;
}
evapi_async_relay("{\"event\":\"CGR_AUTH_REQUEST\",
\"tr_index\":\"$T(id_index)\",
\"tr_label\":\"$T(id_label)\",
\"cgr_subsystems\":\"*attributes;*accounts;*suppliers;*resources;*thresholds\",
\"reply_route\":\"CGR_SESSIONAUTH_REPLY\",
\"Account\":\"$fU\",
\"Destination\":\"$rU\",
\"SetupTime\":\"$TS\"}");
}
# Process SESSIONAUTH_reply from CGRateS
route[CGR_SESSIONAUTH_REPLY] {
json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)");
$var(TransactionIndex) = $(var(TransactionIndex){s.rm,"});
$var(id_index) = $(var(TransactionIndex){s.int});
json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
$var(TransactionLabel) = $(var(TransactionLabel){s.rm,"});
$var(id_label) = $(var(TransactionLabel){s.int});
json_get_field("$evapi(msg)", "Attributes", "$var(cgrAttributes)");
$var(cgrAttributes) = $(var(cgrAttributes){s.rm,"});
json_get_field("$evapi(msg)", "ResourceAllocation", "$var(cgrResourceAllocation)");
$var($var(cgrResourceAllocation)) = $(var(cgrResourceAllocation){s.rm,"});
json_get_field("$evapi(msg)", "MaxUsage", "$var(MaxUsage)");
$var(cgrMaxUsage) = $(var(MaxUsage){s.int});
json_get_field("$evapi(msg)", "Suppliers", "$var(cgrSuppliers)");
$var($var(cgrSuppliers)) = $(var(cgrSuppliers){s.rm,"});
json_get_field("$evapi(msg)", "Error", "$var(cgrError)");
$var(cgrError) = $(var(cgrError){s.rm,"});
t_continue("$var(id_index)", "$var(id_label)", "CGRATES_SESSIONAUTH_REPLY"); # Unpark the transaction
}
# Inform CGRateS about CALL_START (start prepaid sessions loops)
route[CGR_CALL_START] {
if $sht(cgrconn=>cgr) == $null {
xlog("Charging controller unreachable");
exit;
}
evapi_relay("{\"event\":\"CGR_CALL_START\",
\"h_entry\":\"$dlg(h_entry)\",
\"h_id\":\"$dlg(h_id)\",
\"cgr_subsystems\":\"*attributes;*accounts;*resources;*thresholds\",
\"OriginID\":\"$dlg_var(cgrOriginID)\",
\"RequestType\":\"$dlg_var(cgrReqType)\",
\"Tenant\":\"$dlg_var(cgrTenant)\",
\"Account\":\"$dlg_var(cgrAccount)\",
\"Destination\":\"$dlg_var(cgrDestination)\",
\"SetupTime\":\"$dlg_var(SetupTime)\",
\"AnswerTime\":\"$TS\"}");
}
# Inform CGRateS about CALL_END (stop debit loops, perform accounting if desired in this way)
route[CGR_CALL_END] {
if $sht(cgrconn=>cgr) == $null {
xlog("Charging controller unreachable");
exit;
}
$var(callDur) = $TS - $dlg(start_ts);
evapi_relay("{\"event\":\"CGR_CALL_END\",
\"cgr_subsystems\":\"*accounts;*resources\",
\"OriginID\":\"$dlg_var(cgrOriginID)\",
\"RequestType\":\"$dlg_var(cgrReqType)\",
\"Tenant\":\"$dlg_var(cgrTenant)\",
\"Account\":\"$dlg_var(cgrAccount)\",
\"Destination\":\"$dlg_var(cgrDestination)\",
\"AnswerTime\":\"$dlg(start_ts)\",
\"PaypalAccount\":\"$dlg_var(paypalAccount)\",
\"SetupTime\":\"$dlg_var(SetupTime)\",
\"Usage\":\"$var(callDur)\"}");
}

View File

@@ -0,0 +1,439 @@
#!KAMAILIO
# Sample demo config for Kamailio-CGRateS communication
# tested against Kamailio 5.1
####### Defined Values #########
#!define FLT_DIALOG 4
#!define FLT_NATS 5
#!define FLB_NATB 6
#!define FLB_NATSIPPING 7
####### Global Parameters #########
debug=2
log_stderror=no
listen=udp:enp0s3:5060
listen=udp:127.0.0.1:5080
listen=udp:127.0.0.1:5060
listen=udp:enp0s3:5080
memdbg=5
memlog=5
log_facility=LOG_LOCAL0
fork=yes
children=4
tcp_connection_lifetime=3605
use_dns_cache=no
dns_try_ipv6=no
dns_retr_time=1
dns_retr_no=1
dns_servers_no=1
dns_use_search_list=no
####### Modules Section ########
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "nathelper.so"
loadmodule "htable.so"
loadmodule "auth.so"
loadmodule "evapi.so"
loadmodule "json.so"
loadmodule "dialog.so"
loadmodule "jsonrpcs.so"
# ----------------- setting module-specific parameters ---------------
modparam("evapi", "bind_addr", "127.0.0.1:8448")
# ----- tm params -----
modparam("tm", "failure_reply_mode", 3)
modparam("tm", "fr_timer", 30000)
modparam("tm", "fr_inv_timer", 120000)
# ----- rr params -----
modparam("rr", "enable_full_lr", 0)
modparam("rr", "append_fromtag", 0)
# ----- registrar params -----
modparam("registrar", "method_filtering", 1)
modparam("registrar", "max_expires", 3600)
# ----- dialog params -----
modparam("dialog", "dlg_flag", FLT_DIALOG)
modparam("dialog", "send_bye", 1)
modparam("dialog", "timeout_noreset", 1)
# ----- nathelper params -----
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org")
# params needed for NAT traversal in other modules
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
modparam("usrloc", "nat_bflag", FLB_NATB)
# ----- htable params -----
modparam("htable", "htable", "cgrconn=>size=1;")
####### Routing Logic ########
include_file "kamailio-cgrates.cfg"
# Main SIP request routing logic
request_route {
# per request initial checks
route(REQINIT);
# NAT detection
route(NATDETECT);
# CANCEL processing
if (is_method("CANCEL")) {
if (t_check_trans()) {
route(RELAY);
}
exit;
}
# handle requests within SIP dialogs
route(WITHINDLG);
### only initial requests (no To tag)
# handle retransmissions
if(t_precheck_trans()) {
t_check_trans();
exit;
}
t_check_trans();
# record routing for dialog forming requests (in case they are routed)
# - remove preloaded route headers
remove_hf("Route");
if (is_method("INVITE|SUBSCRIBE"))
record_route();
# Not handling requests towards external domains
if uri != myself {
sl_send_reply("604", "Only local destinations accepted");
exit;
}
### requests for my local domains
# SIMPLE AUTH methods
if is_method("REGISTER|SUBSCRIBE|PUBLISH") {
route(CGRATES_SIMPLEAUTH_REQUEST);
exit;
}
if ($rU==$null) {
# request with no Username in RURI
sl_send_reply("484","Address Incomplete");
exit;
}
if !is_method("INVITE") {
sl_send_reply("503", "Unsupported method");
exit;
}
route(CGRATES_SESSIONAUTH_REQUEST);
exit;
}
# Here will land requests after processing them with CGRateS.
route[CGRATES_SIMPLEAUTH_REPLY] {
if $var(cgrError) != "" {
xlog("CGR_PROFILE_ERROR: $var(cgrError)");
sl_send_reply("503","CGR_ERROR");
exit;
}
# parse the CGRateS attributes
route(PARSE_CGRATES_ATTRIBUTES);
# password based auth
route(AUTH);
if is_method("REGISTER") {
route(REGISTRAR);
exit;
}
# other methods going over location
route(LOCATION);
route(RELAY);
}
# Here will land requests after processing them with CGRateS. Call RELAY or other routes following this route
route[CGRATES_SESSIONAUTH_REPLY] {
if $var(cgrError) != "" {
xlog("CGR_AUTH_ERROR: $var(cgrError)");
sl_send_reply("503","CGR_ERROR");
exit;
}
# parse the CGRateS attributes
route(PARSE_CGRATES_ATTRIBUTES);
# password based auth
route(AUTH);
# track the dialog so we can set it's timeout and channel variables to store in CDRs
# cannot initialize the dialog sooner due to AUTH
dlg_manage();
$dlg_var(SetupTime) = $TS;
$dlg_var(cgrOriginID) = $dlg(callid) + ";" + $dlg(from_tag);
$dlg_var(cgrTenant) = "cgrates.org";
$dlg_var(cgrReqType) = $avp(RequestType);
$dlg_var(cgrAccount) = $fU;
$dlg_var(cgrDestination) = $rU;
$dlg_var(paypalAccount) = $avp(PaypalAccount);
if $var(cgrMaxUsage) != -1 {
if $var(cgrMaxUsage) == 0 { // Not enough balance, do not allow the call to go through
sl_send_reply("403","Insufficient credit");
exit;
} else if !dlg_set_timeout("$var(cgrMaxUsage)") {
sl_send_reply("503","CGR_MAX_USAGE_ERROR");
exit;
}
}
if $var(cgrSuppliers) != "" { # Enforce the supplier variable to the first one received from CGRateS, here more for demo purposes
$dlg_var(cgrSupplier) = $(var(cgrSuppliers){s.select,0,,});
}
# user location service
route(LOCATION);
# send out
route(RELAY);
}
# Wrapper for relaying requests
route[RELAY] {
# enable additional event routes for forwarded requests
# - serial forking, RTP relaying handling, a.s.o.
if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
}
if (is_method("INVITE|SUBSCRIBE|UPDATE")) {
if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");
}
if (is_method("INVITE")) {
if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
}
if (!t_relay()) {
sl_reply_error();
}
exit;
}
# Per SIP request initial checks
route[REQINIT] {
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if(is_method("OPTIONS") && uri==myself && $rU==$null) {
sl_send_reply("200","Keepalive");
exit;
}
if(!sanity_check("1511", "7")) {
xlog("Malformed SIP message from $si:$sp\n");
exit;
}
}
# Handle requests within SIP dialogs
route[WITHINDLG] {
if (!has_totag()) return;
# sequential request withing a dialog should
# take the path determined by record-routing
if (loose_route()) {
route(DLGURI);
if ( is_method("ACK") ) {
# ACK is forwarded statelessy
route(NATMANAGE);
}
else if ( is_method("NOTIFY") ) {
# Add Record-Route for in-dialog NOTIFY as per RFC 6665.
record_route();
}
route(RELAY);
exit;
}
if ( is_method("ACK") ) {
if ( t_check_trans() ) {
# no loose-route, but stateful ACK;
# must be an ACK after a 487
# or e.g. 404 from upstream server
route(RELAY);
exit;
} else {
# ACK without matching transaction ... ignore and discard
exit;
}
}
sl_send_reply("404","Not here");
exit;
}
# Handle SIP registrations
route[REGISTRAR] {
if(isflagset(FLT_NATS)) {
setbflag(FLB_NATB);
}
if (!save("location"))
sl_reply_error();
exit;
}
# User location service
route[LOCATION] {
$avp(oexten) = $rU;
if (!lookup("location")) {
$var(rc) = $rc;
t_newtran();
switch ($var(rc)) {
case -1:
case -3:
send_reply("404", "Not Found");
exit;
case -2:
send_reply("405", "Method Not Allowed");
exit;
}
}
}
# user uthentication
route[AUTH] {
if (is_method("REGISTER")) {
if ( strempty($au) || !pv_www_authenticate("$td", "$avp(Password)", "0") ) {
www_challenge("$td", "0");
exit;
}
} else { # All other methods here
if ( strempty($au) || !pv_proxy_authenticate("$td", "$avp(Password)", "0") ) {
proxy_challenge("$td", "0");
exit;
}
}
consume_credentials();
return;
}
# Caller NAT detection
route[NATDETECT] {
force_rport();
if (nat_uac_test("19")) {
if (is_method("REGISTER")) {
fix_nated_register();
} else {
if(is_first_hop())
set_contact_alias();
}
setflag(FLT_NATS);
}
return;
}
# RTPProxy control and singaling updates for NAT traversal
route[NATMANAGE] {
if (is_request()) {
if(has_totag()) {
if(check_route_param("nat=yes")) {
setbflag(FLB_NATB);
}
}
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
return;
if (is_request()) {
if (!has_totag()) {
if(t_is_branch_route()) {
add_rr_param(";nat=yes");
}
}
}
if (is_reply()) {
if(isbflagset(FLB_NATB)) {
if(is_first_hop())
set_contact_alias();
}
}
return;
}
# URI update for dialog requests
route[DLGURI] {
if(!isdsturiset()) {
handle_ruri_alias();
}
return;
}
# Manage outgoing branches
branch_route[MANAGE_BRANCH] {
route(NATMANAGE);
}
# Manage incoming replies
onreply_route[MANAGE_REPLY] {
if(status=~"[12][0-9][0-9]")
route(NATMANAGE);
}
# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
if (t_check_status("3[0-9][0-9]")) {
t_reply("404","Not found");
exit;
}
}

View File

@@ -0,0 +1,139 @@
{
// Real-time Charging System for Telecom & ISP environments
// Copyright (C) ITsysCOM GmbH
//
"listen": {
"rpc_json": ":2012",
"rpc_gob": ":2013",
"http": ":2080",
},
"stor_db": {
"db_password": "CGRateS.org",
},
"scheduler": {
"enabled": true,
},
"rals": {
"enabled": true,
"thresholds_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"}
],
"stats_conns": [
{"address": "127.0.0.1:2012", "transport": "*json"}
],
"attributes_conns": [
{"address": "*internal"}
],
},
"cdrs": {
"enabled": true,
"stats_conns": [
{"address": "*internal"}
],
"chargers_conns": [
{"address": "*internal"}
],
"sessions_cost_retries": 5,
},
"chargers": {
"enabled": true,
"attributes_conns": [
{"address": "*internal"}
],
},
"sessions": {
"enabled": true,
"listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests
"chargers_conns": [
{"address": "*internal"}
],
"rals_conns": [
{"address": "*internal"}
],
"cdrs_conns": [
{"address": "*internal"}
],
"resources_conns": [
{"address": "*internal"}
],
"suppliers_conns": [
{"address": "*internal"}
],
"attributes_conns": [
{"address": "*internal"}
],
"stats_conns": [
{"address": "*internal"}
],
"thresholds_conns": [
{"address": "*internal"}
],
"debit_interval": "5s",
"channel_sync_interval":"7s",
},
"attributes": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"resources": {
"enabled": true,
"thresholds_conns": [
{"address": "*internal"}
],
"string_indexed_fields": ["Account"],
"prefix_indexed_fields": ["Destination"],
},
"stats": {
"enabled": true,
"thresholds_conns": [
{"address": "*internal"}
],
"string_indexed_fields": ["Account"],
},
"thresholds": {
"enabled": true,
"string_indexed_fields": ["Account"],
},
"suppliers": {
"enabled": true,
"rals_conns": [
{"address": "*internal"}
],
"resources_conns": [
{"address": "*internal"}
],
"stats_conns": [
{"address": "*internal"}
],
"string_indexed_fields": ["Account"],
"prefix_indexed_fields": ["Destination"],
},
}

View File

@@ -0,0 +1,175 @@
#! /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
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="CGRateS Online Charging System"
NAME=cgrates
DAEMON=/usr/bin/cgr-engine
USER=cgrates
GROUP=cgrates
DAEMON_OPTS=""
TUTFOLDER=/usr/share/cgrates/tutorial_tests/osips/$NAME
TMP_DIR=/tmp/cgr_osipsnative/$NAME
SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME
RUNDIR=$TMP_DIR/run
PIDFILE=$RUNDIR/cgr-engine.pid
STACKTRACE=$RUNDIR/$NAME.strace
ENABLE=true
DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates"
CDREDIR=$TMP_DIR/cdre
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# 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
touch $STACKTRACE
chown -R $USER:$GROUP $RUNDIR
fi
# Install the cdre folder
if [ ! -d $CDREDIR ]; then
mkdir -p $CDREDIR
chown $USER:$GROUP $CDREDIR
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
echo "\n### Started at:" `date`>>$STACKTRACE
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\
|| return 1
start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\
--startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \
|| 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
:

View File

@@ -0,0 +1,27 @@
#
# 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

View File

@@ -0,0 +1,199 @@
#! /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
TUTDIR=/usr/share/cgrates/tutorial_tests/osips/$NAME
SCRIPTNAME=$TUTDIR/etc/init.d/$NAME
TMP_DIR=/tmp/cgr_osipsnative/$NAME
CFGFILE=$TUTDIR/etc/$NAME/opensips.cfg
M4CFGFILE=/etc/opensips/opensips.m4
M4ARCHIVEDIR=/etc/opensips/archive
HOMEDIR=$TMP_DIR/run/opensips
PIDFILE=$HOMEDIR/$NAME.pid
DEFAULTS=$TUTDIR/etc/default/opensips
RUN_OPENSIPS=no
if [ ! -d $HOMEDIR ]; then
mkdir -p $HOMEDIR
chown -R $USER:$GROUP $HOMEDIR
fi
# 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 -w $HOMEDIR"
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

View File

@@ -0,0 +1,269 @@
#
# 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 #########
log_level=3
log_stderror=no
log_facility=LOG_LOCAL0
udp_workers=4
auto_aliases=no
listen=udp:enp0s3:5060
listen=udp:127.0.0.1:5080
listen=udp:127.0.0.1:5060
listen=udp:enp0s3:5080
####### Modules Section ########
#set module path
mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/"
#### SIGNALING module
loadmodule "signaling.so"
#### StateLess module
loadmodule "sl.so"
#### Transaction Module
loadmodule "tm.so"
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 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)
#### 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")
#### ACCounting module
loadmodule "acc.so"
modparam("acc", "early_media", 0)
modparam("acc", "report_cancels", 0)
modparam("acc", "detect_direction", 0)
loadmodule "proto_udp.so"
#### CGRateS module
loadmodule "dialog.so"
loadmodule "cgrates.so"
modparam("cgrates", "cgrates_engine", "127.0.0.1:2014")
####### Routing Logic ########
# main request routing logic
route{
if (!mf_process_maxfwd_header(10)) {
send_reply(483,"Too Many Hops");
exit;
}
if (has_totag()) {
# handle hop-by-hop ACK (no routing required)
if ( is_method("ACK") && t_check_trans() ) {
t_relay();
exit;
}
# sequential request within a dialog should
# take the path determined by record-routing
if ( !loose_route() ) {
# we do record-routing for all our traffic, so we should not
# receive any sequential requests without Route hdr.
send_reply(404, "Not here");
exit;
}
if (is_method("BYE")) {
# do accounting even if the transaction fails
do_accounting("log","failed");
}
# route it out to whatever destination was set by loose_route()
# in $du (destination URI).
route(relay);
exit;
}
# CANCEL processing
if (is_method("CANCEL")) {
if (t_check_trans())
t_relay();
exit;
}
# absorb retransmissions, but do not create transaction
t_check_trans();
if ( !(is_method("REGISTER") ) ) {
if (is_myself("$fd")) {
} else {
# if caller is not local, then called number must be local
if (!is_myself("$rd")) {
send_reply(403,"Relay 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"))
send_reply(403, "Preload Route denied");
exit;
}
# record routing
if (!is_method("REGISTER|MESSAGE"))
record_route();
if (!is_myself("$rd")) {
append_hf("P-hint: outbound\r\n");
route(relay);
}
# requests for my domain
if (is_method("PUBLISH|SUBSCRIBE")) {
send_reply(503, "Service Unavailable");
exit;
}
if (is_method("REGISTER")) {
if (!save("location"))
sl_reply_error();
exit;
}
if ($rU==NULL) {
# request with no Username in RURI
send_reply(484,"Address Incomplete");
exit;
}
# do lookup with method filtering
if (!lookup("location","m")) {
t_reply(404, "Not Found");
exit;
}
# check auth with CGRateS
$cgr_opt(GetMaxUsage) = 1; # also retrieve the max usage
$cgr_opt(GetAttributes) = 1;
$cgr_opt(GetSuppliers) = 1;
$cgr_opt(AuthorizeResources) = 1;
$cgr_opt(AllocateResources) = 1;
$cgr_opt(ReleaseResources) = 1;
$cgr_opt(ProcessThresholds) = 1;
$cgr_opt(ProcessStatQueues) = 1;
$cgr(RequestType) = "*prepaid";
$cgr(OriginHost) = "127.0.0.1";
$cgr(Source) = "OpenSIPS";
if (!async(cgrates_auth("$fU", "$rU"), resume_cgr_auth)) {
sl_send_reply(503, "Service Unavailable");
exit;
}
}
route [resume_cgr_auth] {
if ($rc != 1) {
xlog("Call not authorized: code=$cgrret!\n");
send_reply(403, "Forbidden");
exit;
}
$var(idx) = 0;
while ($(cgr_ret(AttributesDigest){s.select,$var(idx),,}) != NULL) {
$avp($(cgr_ret(AttributesDigest){s.select,$var(idx),,}{s.select,0,:}))
= $(cgr_ret(AttributesDigest){s.select,$var(idx),,}{s.select,1,:});
$var(idx) = $var(idx) + 1;
}
cgrates_acc("cdr|missed", "$fU", "$rU");
xlog("### Have authorized the call and it should go through");
route(relay);
}
route[relay] {
# for INVITEs enable some additional helper routes
if (is_method("INVITE")) {
t_on_branch("per_branch_ops");
t_on_reply("handle_nat");
t_on_failure("missed_call");
}
if (!t_relay()) {
send_reply(500,"Internal Error");
}
exit;
}
branch_route[per_branch_ops] {
xlog("new branch at $ru\n");
}
onreply_route[handle_nat] {
xlog("incoming reply\n");
}
failure_route[missed_call] {
if (t_was_cancelled()) {
exit;
}
}