mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-21 15:18:44 +05:00
Responder.GetDerivedMaxSessionTime and GetSessionRuns now taking concrete types as parameters instead of interfaces for easy RPC integration, added fs_evsock tutorial files, removed fs_csv and fs_json to keep tutorial simple to maintain
This commit is contained in:
@@ -26,7 +26,7 @@ import (
|
||||
// Returns MaxSessionTime in seconds, -1 for no limit
|
||||
func (self *ApierV1) GetMaxSessionTime(cdr utils.StoredCdr, maxSessionTime *float64) error {
|
||||
var maxDur float64
|
||||
if err := self.Responder.GetDerivedMaxSessionTime(&cdr, &maxDur); err != nil {
|
||||
if err := self.Responder.GetDerivedMaxSessionTime(cdr, &maxDur); err != nil {
|
||||
return err
|
||||
}
|
||||
if maxDur == -1.0 {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
Tutorial FS_CSV
|
||||
===============
|
||||
|
||||
Scenario:
|
||||
---------
|
||||
|
||||
* FreeSWITCH with default configuration.
|
||||
|
||||
* Modified following users: 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated.
|
||||
* Have added inside default dialplan CGR own extensions just before routing towards users.
|
||||
* FreeSWITCH configured to generate default .csv CDRs, modified example template to add cgr_reqtype from user variables.
|
||||
|
||||
* CGRateS with following components:
|
||||
|
||||
* CGR-SM started as prepaid controller.
|
||||
* CGR-CDRC component importing CDRs into CGR.
|
||||
* CGR-CDRE exporting mediated CDRs
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
# CGRateS Configuration file
|
||||
#
|
||||
# This file contains the default configuration hardcoded into CGRateS.
|
||||
# This is what you get when you load CGRateS with an empty configuration file.
|
||||
# [global] must exist in all files, rest of the configuration is inter-changeable.
|
||||
|
||||
[global]
|
||||
# ratingdb_type = redis # Rating subsystem database: <redis>.
|
||||
# ratingdb_host = 127.0.0.1 # Rating subsystem database host address.
|
||||
# ratingdb_port = 6379 # Rating subsystem port to reach the database.
|
||||
# ratingdb_name = 10 # Rating subsystem database name to connect to.
|
||||
# ratingdb_user = # Rating subsystem username to use when connecting to database.
|
||||
# ratingdb_passwd = # Rating subsystem password to use when connecting to database.
|
||||
# accountdb_type = redis # Accounting subsystem database: <redis>.
|
||||
# accountdb_host = 127.0.0.1 # Accounting subsystem database host address.
|
||||
# accountdb_port = 6379 # Accounting subsystem port to reach the database.
|
||||
# accountdb_name = 11 # Accounting subsystem database name to connect to.
|
||||
# accountdb_user = # Accounting subsystem username to use when connecting to database.
|
||||
# accountdb_passwd = # Accounting subsystem password to use when connecting to database.
|
||||
# stordb_type = mysql # Stor database type to use: <mysql>
|
||||
# stordb_host = 127.0.0.1 # The host to connect to. Values that start with / are for UNIX domain sockets.
|
||||
# stordb_port = 3306 # The port to reach the logdb.
|
||||
# stordb_name = cgrates # The name of the log database to connect to.
|
||||
# stordb_user = cgrates # Username to use when connecting to stordb.
|
||||
# stordb_passwd = CGRateS.org # Password to use when connecting to stordb.
|
||||
# dbdata_encoding = msgpack # The encoding used to store object data in strings: <msgpack|json>
|
||||
# rpc_json_listen = 127.0.0.1:2012 # RPC JSON listening address
|
||||
# rpc_gob_listen = 127.0.0.1:2013 # RPC GOB listening address
|
||||
# http_listen = 127.0.0.1:2080 # HTTP listening address
|
||||
# default_reqtype = rated # Default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated>.
|
||||
# default_tor = call # Default Type of Record to consider when missing from requests.
|
||||
# default_tenant = cgrates.org # Default Tenant to consider when missing from requests.
|
||||
# default_subject = cgrates # Default rating Subject to consider when missing from requests.
|
||||
# rounding_method = *middle # Rounding method for floats/costs: <*up|*middle|*down>
|
||||
# rounding_decimals = 4 # Number of decimals to round float/costs at
|
||||
|
||||
[balancer]
|
||||
# enabled = false # Start Balancer service: <true|false>.
|
||||
# listen = 127.0.0.1:2012 # Balancer listen interface: <""|x.y.z.y:1234>.
|
||||
|
||||
[rater]
|
||||
enabled = true # Enable RaterCDRSExportPath service: <true|false>.
|
||||
# balancer = # Register to Balancer as worker: <""|internal|127.0.0.1:2013>.
|
||||
|
||||
[scheduler]
|
||||
enabled = true # Starts Scheduler service: <true|false>.
|
||||
|
||||
[cdrs]
|
||||
enabled = true # Start the CDR Server service: <true|false>.
|
||||
# extra_fields = # Extra fields to store in CDRs
|
||||
mediator = internal # Address where to reach the Mediator. Empty for disabling mediation. <""|internal>
|
||||
|
||||
[cdre]
|
||||
# cdr_format = csv # Exported CDRs format <csv>
|
||||
# extra_fields = # List of extra fields to be exported out in CDRs
|
||||
export_dir = /tmp/cgrates/cdre # Path where the exported CDRs will be placed
|
||||
|
||||
[cdrc]
|
||||
enabled = true # Enable CDR client functionality
|
||||
# cdrs = internal # Address where to reach CDR server. <internal|127.0.0.1:2080>
|
||||
# run_delay = 0 # Sleep interval in seconds between consecutive runs, 0 to use automation via inotify
|
||||
cdr_type = freeswitch_csv # CDR file format <csv>.
|
||||
cdr_in_dir = /tmp/cgrates/cdr/cdrc/in # Absolute path towards the directory where the CDRs are stored.
|
||||
cdr_out_dir = /tmp/cgrates/cdr/cdrc/out # Absolute path towards the directory where processed CDRs will be moved.
|
||||
cdr_source_id = freeswitch_csv # Free form field, tag identifying the source of the CDRs within CGRS database.
|
||||
accid_field = 10 # Accounting id field identifier. Use index number in case of .csv cdrs.
|
||||
reqtype_field = 16 # Request type field identifier. Use index number in case of .csv cdrs.
|
||||
direction_field = ^*out # Direction field identifier. Use index numbers in case of .csv cdrs.
|
||||
tenant_field = ^cgrates.org # Tenant field identifier. Use index numbers in case of .csv cdrs.
|
||||
tor_field = ^call # Type of Record field identifier. Use index numbers in case of .csv cdrs.
|
||||
account_field = 1 # Account field identifier. Use index numbers in case of .csv cdrs.
|
||||
subject_field = 1 # Subject field identifier. Use index numbers in case of .csv CDRs.
|
||||
destination_field = 2 # Destination field identifier. Use index numbers in case of .csv cdrs.
|
||||
answer_time_field = 5 # Answer time field identifier. Use index numbers in case of .csv cdrs.
|
||||
duration_field = 8 # Duration field identifier. Use index numbers in case of .csv cdrs.
|
||||
extra_fields = read_codec:13,write_codec:14 # Extra fields identifiers. For .csv, format: <label_extrafield1>:<index_extrafield_1>
|
||||
|
||||
[mediator]
|
||||
enabled = true # Starts Mediator service: <true|false>.
|
||||
# rater = internal # Address where to reach the Rater: <internal|x.y.z.y:1234>
|
||||
# rater_reconnects = 3 # Number of reconnects to rater before giving up.
|
||||
# run_ids = # Identifiers of each extra mediation to run on CDRs
|
||||
# reqtype_fields = # Name of request type fields to be used during extra mediation. Use index number in case of .csv cdrs.
|
||||
# direction_fields = # Name of direction fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# tenant_fields = # Name of tenant fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# tor_fields = # Name of tor fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# account_fields = # Name of account fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# subject_fields = # Name of fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# destination_fields = # Name of destination fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# answer_time_fields = # Name of time_answer fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
# duration_fields = # Name of duration fields to be used during extra mediation. Use index numbers in case of .csv cdrs.
|
||||
|
||||
[session_manager]
|
||||
enabled = true # Starts SessionManager service: <true|false>.
|
||||
# switch_type = freeswitch # Defines the type of switch behind: <freeswitch>.
|
||||
# rater = internal # Address where to reach the Rater.
|
||||
# rater_reconnects = 3 # Number of reconnects to rater before giving up.
|
||||
# debit_interval = 5 # Interval to perform debits on.
|
||||
|
||||
[freeswitch]
|
||||
# server = 127.0.0.1:8021 # Adress where to connect to FreeSWITCH socket.
|
||||
# passwd = ClueCon # FreeSWITCH socket password.
|
||||
# reconnects = 5 # 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.
|
||||
# save_interval = 1s # Interval to save changed cache into .git archive
|
||||
|
||||
[history_agent]
|
||||
# enabled = false # Starts History as a client: <true|false>.
|
||||
# server = internal # Address where to reach the master history server: <internal|x.y.z.y:1234>
|
||||
|
||||
[mailer]
|
||||
# server = localhost # The server to use when sending emails out
|
||||
# auth_user = cgrates # Authenticate to email server using this user
|
||||
# auth_passwd = CGRateS.org # Authenticate to email server with this password
|
||||
# from_address = cgr-mailer@localhost.localdomain # From address used when sending emails out
|
||||
|
||||
@@ -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=''
|
||||
|
||||
# Don't forget to create an appropriate config file,
|
||||
# else the CGRateS system will not start.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# /etc/default/freeswitch
|
||||
DAEMON_OPTS="-rp -nonat"
|
||||
Binary file not shown.
@@ -1,135 +0,0 @@
|
||||
#!/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/tutorials/fs_csv/freeswitch
|
||||
CONFDIR=$TUTDIR/etc/$NAME
|
||||
DEFAULTS=$TUTDIR/etc/default/freeswitch
|
||||
RUNDIR=/var/run/$NAME
|
||||
LOGDIR=/var/log/freeswitch
|
||||
PIDFILE=$RUNDIR/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
WORKDIR=/var/lib/$NAME
|
||||
DBDIR=$WORKDIR/db/
|
||||
DAEMON_ARGS="-rp -conf $CONFDIR -db $DBDIR -log $LOGDIR -u $USER -g $GROUP -nonat -nc"
|
||||
|
||||
|
||||
[ -x $DAEMON ] || exit 0
|
||||
[ -r DEFAULTS ] && . DEFAULTS
|
||||
. /lib/init/vars.sh
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
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
|
||||
|
||||
# Directory in /var/run may disappear on reboot (e.g. when tmpfs used for /var/run).
|
||||
mkdir -p $RUNDIR
|
||||
chown -R $USER:$GROUP $RUNDIR
|
||||
chmod -R ug=rwX,o= $RUNDIR
|
||||
|
||||
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
|
||||
@@ -4,15 +4,15 @@ Tutorial FS_JSON
|
||||
Scenario:
|
||||
---------
|
||||
|
||||
- FreeSWITCH with *vanilla* configuration, replacing *mod_cdr_csv* with *mod_json_cdr*.
|
||||
- FreeSWITCH with minimal custom configuration.
|
||||
|
||||
- Modified following users (with configs in *etc/freeswitch/directory/default*): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1006-prepaid, 1007-prepaid.
|
||||
- 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*).
|
||||
- FreeSWITCH configured to generate default *http-json* CDRs.
|
||||
|
||||
- **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.
|
||||
- CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*).
|
||||
253
data/tutorials/fs_evsock/cgrates/etc/cgrates/cgrates.json
Normal file
253
data/tutorials/fs_evsock/cgrates/etc/cgrates/cgrates.json
Normal file
@@ -0,0 +1,253 @@
|
||||
{
|
||||
|
||||
// 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.
|
||||
|
||||
|
||||
//"general": {
|
||||
// "http_skip_tls_veify": false, // if enabled Http Client will accept any TLS certificate
|
||||
// "rounding_decimals": 10, // system level precision for floats
|
||||
// "dbdata_encoding": "msgpack", // encoding used to store object data in strings: <msgpack|json>
|
||||
// "tpexport_dir": "/var/log/cgrates/tpe", // path towards export folder for offline Tariff Plans
|
||||
// "default_reqtype": "rated", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated>
|
||||
// "default_category": "call", // default Type of Record to consider when missing from requests
|
||||
// "default_tenant": "cgrates.org", // default Tenant to consider when missing from requests
|
||||
// "default_subject": "cgrates", // default rating Subject to consider when missing from requests
|
||||
//},
|
||||
|
||||
|
||||
//"listen": {
|
||||
// "rpc_json": "127.0.0.1:2012", // RPC JSON listening address
|
||||
// "rpc_gob": "127.0.0.1:2013", // RPC GOB listening address
|
||||
// "http": "127.0.0.1:2080", // HTTP listening address
|
||||
//},
|
||||
|
||||
|
||||
//"rating_db": {
|
||||
// "db_type": "redis", // rating subsystem database type: <redis>
|
||||
// "db_host": "127.0.0.1", // rating subsystem database host address
|
||||
// "db_port": 6379, // rating subsystem port to reach the database
|
||||
// "db_name": "10", // rating subsystem database name to connect to
|
||||
// "db_user": "", // rating subsystem username to use when connecting to database
|
||||
// "db_passwd": "", // rating subsystem password to use when connecting to database
|
||||
//},
|
||||
|
||||
|
||||
//"accounting_db": {
|
||||
// "db_type": "redis", // accounting subsystem database: <redis>
|
||||
// "db_host": "127.0.0.1", // accounting subsystem database host address
|
||||
// "db_port": 6379, // accounting subsystem port to reach the database
|
||||
// "db_name": "11", // accounting subsystem database name to connect to
|
||||
// "db_user": "", // accounting subsystem username to use when connecting to database
|
||||
// "db_passwd": "", // accounting subsystem password to use when connecting to database
|
||||
//},
|
||||
|
||||
|
||||
//"stor_db": {
|
||||
// "db_type": "mysql", // stor database type to use: <mysql|postgres>
|
||||
// "db_host": "127.0.0.1", // the host to connect to
|
||||
// "db_port": 3306, // the port to reach the stordb
|
||||
// "db_name": "cgrates", // stor database name
|
||||
// "db_user": "cgrates", // username to use when connecting to stordb
|
||||
// "db_passwd": "CGRateS.org", // password to use when connecting to stordb
|
||||
// "max_open_conns": 0, // maximum database connections opened
|
||||
// "max_idle_conns": -1, // maximum database connections idle
|
||||
//},
|
||||
|
||||
|
||||
//"balancer": {
|
||||
// "enabled": false, // start Balancer service: <true|false>
|
||||
//},
|
||||
|
||||
|
||||
"rater": {
|
||||
"enabled": true, // enable Rater service: <true|false>
|
||||
// "balancer": "", // register to Balancer as worker: <""|internal|x.y.z.y:1234>
|
||||
},
|
||||
|
||||
|
||||
"scheduler": {
|
||||
"enabled": true, // start Scheduler service: <true|false>
|
||||
},
|
||||
|
||||
|
||||
"cdrs": {
|
||||
"enabled": true, // start the CDR Server service: <true|false>
|
||||
// "extra_fields": [], // extra fields to store in CDRs for non-generic CDRs
|
||||
"mediator": "internal", // address where to reach the Mediator. Empty for disabling mediation. <""|internal>
|
||||
"cdrstats": "internal", // address where to reach the cdrstats service. Empty to disable stats gathering from raw CDRs <""|internal|x.y.z.y:1234>
|
||||
// "store_disable": false, // when true, CDRs will not longer be saved in stordb, useful for cdrstats only scenario
|
||||
},
|
||||
|
||||
|
||||
"mediator": {
|
||||
"enabled": true, // starts Mediator service: <true|false>.
|
||||
// "reconnects": 3, // number of reconnects to rater/cdrs before giving up.
|
||||
"rater": "internal", // address where to reach the Rater: <internal|x.y.z.y:1234>
|
||||
"cdrstats": "internal", // address where to reach the cdrstats service. Empty to disable stats gathering out of mediated CDRs <""|internal|x.y.z.y:1234>
|
||||
// "store_disable": false, // when true, CDRs will not longer be saved in stordb, useful for cdrstats only scenario
|
||||
},
|
||||
|
||||
|
||||
"cdrstats": {
|
||||
"enabled": true, // starts the cdrstats service: <true|false>
|
||||
// "queue_length": 50, // number of items in the stats buffer
|
||||
// "time_window": "1h", // will only keep the CDRs who's call setup time is not older than time.Now()-TimeWindow
|
||||
// "metrics": ["ASR", "ACD", "ACC"], // stat metric ids to build
|
||||
// "setup_interval": [], // filter on CDR SetupTime
|
||||
// "tors": [], // filter on CDR TOR fields
|
||||
// "cdr_hosts": [], // filter on CDR CdrHost fields
|
||||
// "cdr_sources": [], // filter on CDR CdrSource fields
|
||||
// "req_types": [], // filter on CDR ReqType fields
|
||||
// "directions": [], // filter on CDR Direction fields
|
||||
// "tenants": [], // filter on CDR Tenant fields
|
||||
// "categories": [], // filter on CDR Category fields
|
||||
// "accounts": [], // filter on CDR Account fields
|
||||
// "subjects": [], // filter on CDR Subject fields
|
||||
// "destination_prefixes": [], // filter on CDR Destination prefixes
|
||||
// "usage_interval": [], // filter on CDR Usage
|
||||
// "mediation_run_ids": [], // filter on CDR MediationRunId fields
|
||||
// "rated_accounts": [], // filter on CDR RatedAccount fields
|
||||
// "rated_subjects": [], // filter on CDR RatedSubject fields
|
||||
// "cost_interval": [], // filter on CDR Cost
|
||||
},
|
||||
|
||||
|
||||
"cdre": {
|
||||
"*default": {
|
||||
"cdr_format": "csv", // exported CDRs format <csv>
|
||||
"field_separator": ",",
|
||||
"data_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from KBytes to Bytes)
|
||||
"sms_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from SMS unit to call duration in some billing systems)
|
||||
"cost_multiply_factor": 1, // multiply cost before export, eg: add VAT
|
||||
"cost_rounding_decimals": -1, // rounding decimals for Cost values. -1 to disable rounding
|
||||
"cost_shift_digits": 0, // shift digits in the cost on export (eg: convert from EUR to cents)
|
||||
"mask_destination_id": "MASKED_DESTINATIONS", // destination id containing called addresses to be masked on export
|
||||
"mask_length": 0, // length of the destination suffix to be masked
|
||||
"export_dir": "/tmp/cgr_fsevsock/cgrates/cdre", // path where the exported CDRs will be placed
|
||||
"header_fields": [], // template of the exported header fields
|
||||
"content_fields": [ // template of the exported content fields
|
||||
{"tag": "CgrId", "cdr_field_id": "cgrid", "type": "cdrfield", "value": "cgrid"},
|
||||
{"tag":"RunId", "cdr_field_id": "mediation_runid", "type": "cdrfield", "value": "mediation_runid"},
|
||||
{"tag":"Tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "tor"},
|
||||
{"tag":"AccId", "cdr_field_id": "accid", "type": "cdrfield", "value": "accid"},
|
||||
{"tag":"ReqType", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "reqtype"},
|
||||
{"tag":"Direction", "cdr_field_id": "direction", "type": "cdrfield", "value": "direction"},
|
||||
{"tag":"Tenant", "cdr_field_id": "tenant", "type": "cdrfield", "value": "tenant"},
|
||||
{"tag":"Category", "cdr_field_id": "category", "type": "cdrfield", "value": "category"},
|
||||
{"tag":"Account", "cdr_field_id": "account", "type": "cdrfield", "value": "account"},
|
||||
{"tag":"Subject", "cdr_field_id": "subject", "type": "cdrfield", "value": "subject"},
|
||||
{"tag":"Destination", "cdr_field_id": "destination", "type": "cdrfield", "value": "destination"},
|
||||
{"tag":"SetupTime", "cdr_field_id": "setup_time", "type": "cdrfield", "value": "setup_time", "layout": "2006-01-02T15:04:05Z07:00"},
|
||||
{"tag":"AnswerTime", "cdr_field_id": "answer_time", "type": "cdrfield", "value": "answer_time", "layout": "2006-01-02T15:04:05Z07:00"},
|
||||
{"tag":"Usage", "cdr_field_id": "usage", "type": "cdrfield", "value": "usage"},
|
||||
{"tag":"Cost", "cdr_field_id": "cost", "type": "cdrfield", "value": "cost"},
|
||||
],
|
||||
"trailer_fields": [], // template of the exported trailer fields
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//"cdrc": {
|
||||
// "*default": {
|
||||
// "enabled": false, // enable CDR client functionality
|
||||
// "cdrs_address": "internal", // address where to reach CDR server. <internal|x.y.z.y:1234>
|
||||
// "cdr_format": "csv", // CDR file format <csv|freeswitch_csv|fwv>
|
||||
// "field_separator": ",", // separator used in case of csv files
|
||||
// "run_delay": 0, // sleep interval in seconds between consecutive runs, 0 to use automation via inotify
|
||||
// "data_usage_multiply_factor": 1024, // conversion factor for data usage
|
||||
// "cdr_in_dir": "/var/log/cgrates/cdrc/in", // absolute path towards the directory where the CDRs are stored
|
||||
// "cdr_out_dir": "/var/log/cgrates/cdrc/out", // absolute path towards the directory where processed CDRs will be moved
|
||||
// "cdr_source_id": "freeswitch_csv", // free form field, tag identifying the source of the CDRs within CDRS database
|
||||
// "cdr_filter": "", // Filter CDR records to import
|
||||
// "cdr_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
|
||||
// {"tag": "tor", "cdr_field_id": "tor", "type": "cdrfield", "value": "2", "mandatory": true},
|
||||
// {"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "3", "mandatory": true},
|
||||
// {"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "4", "mandatory": true},
|
||||
// {"tag": "direction", "cdr_field_id": "direction", "type": "cdrfield", "value": "5", "mandatory": true},
|
||||
// {"tag": "tenant", "cdr_field_id": "tenant", "type": "cdrfield", "value": "6", "mandatory": true},
|
||||
// {"tag": "category", "cdr_field_id": "category", "type": "cdrfield", "value": "7", "mandatory": true},
|
||||
// {"tag": "account", "cdr_field_id": "account", "type": "cdrfield", "value": "8", "mandatory": true},
|
||||
// {"tag": "subject", "cdr_field_id": "subject", "type": "cdrfield", "value": "9", "mandatory": true},
|
||||
// {"tag": "destination", "cdr_field_id": "destination", "type": "cdrfield", "value": "10", "mandatory": true},
|
||||
// {"tag": "setup_time", "cdr_field_id": "setup_time", "type": "cdrfield", "value": "11", "mandatory": true},
|
||||
// {"tag": "answer_time", "cdr_field_id": "answer_time", "type": "cdrfield", "value": "12", "mandatory": true},
|
||||
// {"tag": "usage", "cdr_field_id": "usage", "type": "cdrfield", "value": "13", "mandatory": true},
|
||||
// ],
|
||||
// }
|
||||
//},
|
||||
|
||||
|
||||
"sm_freeswitch": {
|
||||
"enabled": true, // starts SessionManager service: <true|false>
|
||||
"rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
|
||||
"cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234>
|
||||
// "reconnects": 5, // number of reconnect attempts to rater or cdrs
|
||||
// "cdr_extra_fields": [], // extra fields to store in CDRs in case of processing them
|
||||
"debit_interval": "5s", // interval to perform debits on.
|
||||
// "min_call_duration": "0s", // only authorize calls with allowed duration higher than this
|
||||
// "max_call_duration": "3h", // maximum call duration a prepaid call can last
|
||||
// "min_dur_low_balance": "5s", // threshold which will trigger low balance warnings for prepaid calls (needs to be lower than debit_interval)
|
||||
// "low_balance_ann_file": "", // file to be played when low balance is reached for prepaid calls
|
||||
// "empty_balance_context": "", // if defined, prepaid calls will be transfered to this context on empty balance
|
||||
// "empty_balance_ann_file": "", // file to be played before disconnecting prepaid calls on empty balance (applies only if no context defined)
|
||||
// "connections":[ // instantiate connections to multiple FreeSWITCH servers
|
||||
// {"server": "127.0.0.1:8021", "password": "ClueCon", "reconnects": -1} // reconnects -1 to indefinitely connect
|
||||
// ],
|
||||
},
|
||||
|
||||
|
||||
//"sm_kamailio": {
|
||||
// "enabled": false, // starts SessionManager service: <true|false>
|
||||
// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
|
||||
// "cdrs": "", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234>
|
||||
// "reconnects": 5, // number of reconnect attempts to rater or cdrs
|
||||
// "debit_interval": "10s", // interval to perform debits on.
|
||||
// "min_call_duration": "0s", // only authorize calls with allowed duration higher than this
|
||||
// "max_call_duration": "3h", // maximum call duration a prepaid call can last
|
||||
// "connections":[ // instantiate connections to multiple Kamailio servers
|
||||
// {"evapi_addr": "127.0.0.1:8448", "reconnects": -1} // reconnects -1 to indefinitely connect
|
||||
// ],
|
||||
//},
|
||||
|
||||
|
||||
//"sm_opensips": {
|
||||
// "enabled": false, // starts SessionManager service: <true|false>
|
||||
// "listen_udp": "127.0.0.1:2020", // address where to listen for datagram events coming from OpenSIPS
|
||||
// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
|
||||
// "cdrs": "", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234>
|
||||
// "debit_interval": "10s", // interval to perform debits on.
|
||||
// "min_call_duration": "0s", // only authorize calls with allowed duration higher than this
|
||||
// "max_call_duration": "3h", // maximum call duration a prepaid call can last
|
||||
// "events_subscribe_interval": "60s", // automatic events subscription to OpenSIPS, 0 to disable it
|
||||
// "mi_addr": "127.0.0.1:8020", // address where to reach OpenSIPS MI to send session disconnects
|
||||
// "reconnects": -1, // reconnects -1 to indefinitely connect
|
||||
//},
|
||||
|
||||
|
||||
|
||||
"history_server": {
|
||||
"enabled": true, // starts History service: <true|false>.
|
||||
"history_dir": "/tmp/cgr_fsevsock/cgrates/history", // location on disk where to store history files.
|
||||
// "save_interval": "1s", // interval to save changed cache into .git archive
|
||||
},
|
||||
|
||||
|
||||
"history_agent": {
|
||||
"enabled": true, // starts History as a client: <true|false>.
|
||||
// "server": "internal", // address where to reach the master history server: <internal|x.y.z.y:1234>
|
||||
},
|
||||
|
||||
|
||||
//"mailer": {
|
||||
// "server": "localhost", // the server to use when sending emails out
|
||||
// "auth_user": "cgrates", // authenticate to email server using this user
|
||||
// "auth_passwd": "CGRateS.org", // authenticate to email server with this password
|
||||
// "from_address": "cgr-mailer@localhost.localdomain" // from address used when sending emails out
|
||||
//},
|
||||
|
||||
}
|
||||
|
||||
@@ -14,31 +14,27 @@
|
||||
# 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/fs_json/cgrates
|
||||
ENGINE_OPTS=-config=$TUTFOLDER/etc/cgrates/cgrates.cfg
|
||||
PIDFILE=/tmp/cgr-engine_tutfsjson.pid
|
||||
DAEMON_OPTS=""
|
||||
TUTFOLDER=/usr/share/cgrates/tutorials/fs_evsock/cgrates
|
||||
TMP_DIR=/tmp/cgr_evsock/cgrates
|
||||
SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME
|
||||
DEFAULTS=$TUTFOLDER/etc/default/$NAME
|
||||
ENABLE=false
|
||||
HISTDIR=/tmp/$NAME/history
|
||||
CDREDIR=/tmp/$NAME/cdre
|
||||
CDRCINDIR=/tmp/$NAME/cdr/cdrc/in
|
||||
CDRCOUTDIR=/tmp/cgrates/cdr/cdrc/out
|
||||
RUNDIR=$TMP_DIR/run
|
||||
PIDFILE=$RUNDIR/cgr-engine.pid
|
||||
STACKTRACE=$RUNDIR/$NAME.strace
|
||||
ENABLE=true
|
||||
DAEMON_OPTS="-config_dir=/usr/share/cgrates/tutorials/fs_evsock/cgrates/etc/cgrates"
|
||||
HISTDIR=$TMP_DIR/history
|
||||
CDREDIR=$TMP_DIR/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
|
||||
|
||||
@@ -55,7 +51,8 @@ fi
|
||||
# Install the run folder
|
||||
if [ ! -d $RUNDIR ]; then
|
||||
mkdir -p $RUNDIR
|
||||
chown $USER:$GROUP $RUNDIR
|
||||
touch $STACKTRACE
|
||||
chown -R $USER:$GROUP $RUNDIR
|
||||
fi
|
||||
# Install the cdre folder
|
||||
if [ ! -d $CDREDIR ]; then
|
||||
@@ -67,15 +64,6 @@ if [ ! -d $HISTDIR ]; then
|
||||
mkdir -p $HISTDIR
|
||||
chown $USER:$GROUP $HISTDIR
|
||||
fi
|
||||
if [ ! -d $CDRCINDIR ]; then
|
||||
mkdir -p $CDRCINDIR
|
||||
chown $USER:$GROUP $CDRCINDIR
|
||||
fi
|
||||
if [ ! -d $CDRCOUTDIR ]; then
|
||||
mkdir -p $CDRCOUTDIR
|
||||
chown $USER:$GROUP $CDRCOUTDIR
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
@@ -86,11 +74,12 @@ do_start()
|
||||
# 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 \
|
||||
echo "\n### Started at:" `date`>>$STACKTRACE
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --exec $DAEMON --chuid $USER:$GROUP --background -- \
|
||||
$ENGINE_OPTS \
|
||||
|| return 2
|
||||
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
|
||||
}
|
||||
|
||||
#
|
||||
@@ -21,14 +21,14 @@ DAEMON=/usr/bin/cgr-engine
|
||||
USER=cgrates
|
||||
GROUP=cgrates
|
||||
DAEMON_OPTS=""
|
||||
TUTFOLDER=/usr/share/cgrates/tutorials/fs_json/cgrates
|
||||
TMP_DIR=/tmp/cgr_fsjson/cgrates
|
||||
TUTFOLDER=/usr/share/cgrates/tutorials/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_dir=/usr/share/cgrates/tutorials/fs_json/cgrates/etc/cgrates"
|
||||
DAEMON_OPTS="-config_dir=$TUTFOLDER/etc/cgrates"
|
||||
HISTDIR=$TMP_DIR/history
|
||||
CDREDIR=$TMP_DIR/cdre
|
||||
|
||||
@@ -75,7 +75,6 @@ do_start()
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
echo "\n### Started at:" `date`>>$STACKTRACE
|
||||
echo $DAEMON $DAEMON_OPTS $PIDFILE
|
||||
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\
|
||||
BIN
data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz
Normal file
BIN
data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz
Normal file
Binary file not shown.
@@ -18,9 +18,9 @@ NAME=freeswitch
|
||||
DAEMON=/usr/bin/freeswitch
|
||||
USER=freeswitch
|
||||
GROUP=freeswitch
|
||||
TUTDIR=/usr/share/cgrates/tutorials/fs_json/freeswitch
|
||||
TUTDIR=/usr/share/cgrates/tutorials/fs_evsock/freeswitch
|
||||
SCRIPTNAME=$TUTDIR/etc/init.d/$NAME
|
||||
TMP_DIR=/tmp/cgr_fsjson/freeswitch
|
||||
TMP_DIR=/tmp/cgr_fsevsock/freeswitch
|
||||
CONFDIR=$TUTDIR/etc/$NAME
|
||||
RUNDIR=$TMP_DIR//run
|
||||
LOGDIR=$TMP_DIR/log
|
||||
Binary file not shown.
@@ -126,7 +126,7 @@ func (rs *Responder) GetMaxSessionTime(arg CallDescriptor, reply *float64) (err
|
||||
}
|
||||
|
||||
// Returns MaxSessionTime for an event received in SessionManager, considering DerivedCharging for it
|
||||
func (rs *Responder) GetDerivedMaxSessionTime(ev utils.Event, reply *float64) error {
|
||||
func (rs *Responder) GetDerivedMaxSessionTime(ev utils.StoredCdr, reply *float64) error {
|
||||
if rs.Bal != nil {
|
||||
return errors.New("Unsupported method on the balancer")
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev utils.Event, reply *float64) er
|
||||
}
|
||||
|
||||
// Used by SM to get all the prepaid CallDescriptors attached to a session
|
||||
func (rs *Responder) GetSessionRuns(ev utils.Event, sRuns *[]*SessionRun) error {
|
||||
func (rs *Responder) GetSessionRuns(ev utils.StoredCdr, sRuns *[]*SessionRun) error {
|
||||
if rs.Bal != nil {
|
||||
return errors.New("Unsupported method on the balancer")
|
||||
}
|
||||
@@ -397,8 +397,8 @@ type Connector interface {
|
||||
RefundIncrements(CallDescriptor, *float64) error
|
||||
GetMaxSessionTime(CallDescriptor, *float64) error
|
||||
GetDerivedChargers(utils.AttrDerivedChargers, *utils.DerivedChargers) error
|
||||
GetDerivedMaxSessionTime(utils.Event, *float64) error
|
||||
GetSessionRuns(utils.Event, *[]*SessionRun) error
|
||||
GetDerivedMaxSessionTime(utils.StoredCdr, *float64) error
|
||||
GetSessionRuns(utils.StoredCdr, *[]*SessionRun) error
|
||||
ProcessCdr(*utils.StoredCdr, *string) error
|
||||
}
|
||||
|
||||
@@ -426,11 +426,11 @@ func (rcc *RPCClientConnector) GetMaxSessionTime(cd CallDescriptor, resp *float6
|
||||
return rcc.Client.Call("Responder.GetMaxSessionTime", cd, resp)
|
||||
}
|
||||
|
||||
func (rcc *RPCClientConnector) GetDerivedMaxSessionTime(ev utils.Event, reply *float64) error {
|
||||
func (rcc *RPCClientConnector) GetDerivedMaxSessionTime(ev utils.StoredCdr, reply *float64) error {
|
||||
return rcc.Client.Call("Responder.GetDerivedMaxSessionTime", ev, reply)
|
||||
}
|
||||
|
||||
func (rcc *RPCClientConnector) GetSessionRuns(ev utils.Event, sRuns *[]*SessionRun) error {
|
||||
func (rcc *RPCClientConnector) GetSessionRuns(ev utils.StoredCdr, sRuns *[]*SessionRun) error {
|
||||
return rcc.Client.Call("Responder.GetSessionRuns", ev, sRuns)
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ func (sm *FSSessionManager) unparkCall(uuid, connId, call_dest_nb, notify string
|
||||
|
||||
func (sm *FSSessionManager) onChannelPark(ev utils.Event, connId string) {
|
||||
var maxCallDuration float64 // This will be the maximum duration this channel will be allowed to last
|
||||
if err := sm.rater.GetDerivedMaxSessionTime(ev, &maxCallDuration); err != nil {
|
||||
if err := sm.rater.GetDerivedMaxSessionTime(*ev.AsStoredCdr(), &maxCallDuration); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Could not get max session time for %s, error: %s", ev.GetUUID(), err.Error()))
|
||||
}
|
||||
maxCallDur := time.Duration(maxCallDuration)
|
||||
|
||||
@@ -58,7 +58,7 @@ func (self *KamailioSessionManager) onCgrAuth(evData []byte, connId string) {
|
||||
return
|
||||
}
|
||||
var remainingDuration float64
|
||||
if err = self.rater.GetDerivedMaxSessionTime(kev.AsEvent(""), &remainingDuration); err != nil {
|
||||
if err = self.rater.GetDerivedMaxSessionTime(*kev.AsStoredCdr(), &remainingDuration); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<SM-Kamailio> Could not get max session time for %s, error: %s", kev.GetUUID(), err.Error()))
|
||||
}
|
||||
if kar, err := kev.AsKamAuthReply(remainingDuration, err); err != nil {
|
||||
|
||||
@@ -262,6 +262,7 @@ func (kev KamEvent) ParseEventValue(rsrFld *utils.RSRField) string {
|
||||
func (kev KamEvent) PassesFieldFilter(*utils.RSRField) (bool, string) {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func (kev KamEvent) AsStoredCdr() *utils.StoredCdr {
|
||||
storCdr := new(utils.StoredCdr)
|
||||
storCdr.CgrId = kev.GetCgrId()
|
||||
|
||||
@@ -58,7 +58,7 @@ func NewSession(ev utils.Event, connId string, sm SessionManager) *Session {
|
||||
sessionManager: sm,
|
||||
connId: connId,
|
||||
}
|
||||
if err := sm.Rater().GetSessionRuns(ev, &s.sessionRuns); err != nil || len(s.sessionRuns) == 0 {
|
||||
if err := sm.Rater().GetSessionRuns(*ev.AsStoredCdr(), &s.sessionRuns); err != nil || len(s.sessionRuns) == 0 {
|
||||
return nil
|
||||
}
|
||||
for runIdx := range s.sessionRuns {
|
||||
|
||||
Reference in New Issue
Block a user