Merge branch 'master' into load

This commit is contained in:
Radu Ioan Fericean
2015-06-03 21:49:12 +03:00
7 changed files with 130 additions and 24 deletions

View File

@@ -0,0 +1,28 @@
{
// Contains CDRC template for FreeSWITCH CDR
"cdrc": {
"CDRC-FS": {
"enabled": true, // enable CDR client functionality
"cdr_in_dir": "/tmp/cgr_fsevsock/cgrates/cdrc/in", // absolute path towards the directory where the CDRs are stored
"cdr_out_dir": "/tmp/cgr_fsevsock/cgrates/cdrc/out", // absolute path towards the directory where processed CDRs will be moved
"cdr_source_id": "fs_csv", // free form field, tag identifying the source of the CDRs within CDRS database
"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": "^*voice", "mandatory": true},
{"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "10", "mandatory": true},
{"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "^*pseudoprepaid", "mandatory": true},
{"tag": "direction", "cdr_field_id": "direction", "type": "cdrfield", "value": "^*out", "mandatory": true},
{"tag": "tenant", "cdr_field_id": "tenant", "type": "cdrfield", "value": "^cgrates.org", "mandatory": true},
{"tag": "category", "cdr_field_id": "category", "type": "cdrfield", "value": "^call", "mandatory": true},
{"tag": "account", "cdr_field_id": "account", "type": "cdrfield", "value": "12", "mandatory": true},
{"tag": "subject", "cdr_field_id": "subject", "type": "cdrfield", "value": "12", "mandatory": true},
{"tag": "destination", "cdr_field_id": "destination", "type": "cdrfield", "value": "2", "mandatory": true},
{"tag": "setup_time", "cdr_field_id": "setup_time", "type": "cdrfield", "value": "4", "mandatory": true},
{"tag": "answer_time", "cdr_field_id": "answer_time", "type": "cdrfield", "value": "5", "mandatory": true},
{"tag": "usage", "cdr_field_id": "usage", "type": "cdrfield", "value": "~8:s/^(\\d+)$/${1}s/", "mandatory": true},
],
},
},
}

View File

@@ -31,6 +31,8 @@ ENABLE=true
DAEMON_OPTS="-config_dir=$TUTFOLDER/etc/cgrates"
HISTDIR=$TMP_DIR/history
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
@@ -54,6 +56,13 @@ if [ ! -d $RUNDIR ]; then
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

View File

@@ -140,23 +140,49 @@
{"tag":"Cost", "cdr_field_id": "cost", "type": "cdrfield", "value": "cost"},
],
"trailer_fields": [], // template of the exported trailer fields
},
"customer_tpl": {
"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_kamevapi/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":"AccId", "cdr_field_id": "accid", "type": "cdrfield", "value": "accid"},
{"tag":"ReqType", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "reqtype"},
{"tag":"Tenant", "cdr_field_id": "tenant", "type": "cdrfield", "value": "tenant"},
{"tag":"Category", "cdr_field_id": "category", "type": "cdrfield", "value": "category"},
{"tag":"Subject", "cdr_field_id": "account", "type": "cdrfield", "value": "account"},
{"tag":"Destination", "cdr_field_id": "destination", "type": "cdrfield", "value": "~destination:s/^1(\\d+)/+$1/:s/^\\+(\\d+)/00$1/"},
{"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
// "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},
@@ -170,7 +196,7 @@
// {"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},
// ],
// }
// },
//},

View File

@@ -7,16 +7,16 @@ event_route[evapi:connection-new] {
# 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;
}
$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
route($(var(Event){s.rm,"})); # String characters are kept by json_get_field, remove them here
}
# Called by Kamailio on new dialog
@@ -56,10 +56,41 @@ route[CGRATES_AUTH_REQUEST] {
# Process AUTH_REPLY from CGRateS
route[CGR_AUTH_REPLY] {
json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)");
json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
json_get_field("$evapi(msg)", "MaxSessionTime", "$var(MaxSessionTime)");
json_get_field("$evapi(msg)", "Suppliers", "$var(Suppliers)");
json_get_field("$evapi(msg)", "Error", "$var(Error)");
json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
json_get_field("$evapi(msg)", "MaxSessionTime", "$var(MaxSessionTime)");
json_get_field("$evapi(msg)", "Suppliers", "$var(Suppliers)");
json_get_field("$evapi(msg)", "Error", "$var(Error)");
$var(id_index) = $(var(TransactionIndex){s.int});
$var(id_label) = $(var(TransactionLabel){s.int});
$var(CgrMaxSessionTime) = $(var(MaxSessionTime){s.int});
$var(CgrSuppliers) = $(var(Suppliers){s.rm,"});
$var(CgrError) = $(var(Error){s.rm,"});
t_continue("$var(id_index)", "$var(id_label)", "CGRATES_AUTH_REPLY"); # Unpark the transaction
}
# Send AUTH_REQUEST to CGRateS
route[CGRATES_LCR_REQUEST] {
# Auth INVITEs with CGRateS
if $sht(cgrconn=>cgr) == $null {
sl_send_reply("503","Charging controller unreachable");
exit;
}
evapi_async_relay("{\"event\":\"CGR_LCR_REQUEST\",
\"tr_index\":\"$T(id_index)\",
\"tr_label\":\"$T(id_label)\",
\"cgr_tenant\":\"$dlg_var(cgrTenant)\",
\"cgr_account\":\"$dlg_var(cgrAccount)\",
\"cgr_destination\":\"$dlg_var(cgrDestination)\",
\"cgr_setuptime\":\"$TS\"}");
}
# Process LCR_REPLY from CGRateS
route[CGR_LCR_REPLY] {
json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)");
json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
json_get_field("$evapi(msg)", "MaxSessionTime", "$var(MaxSessionTime)");
json_get_field("$evapi(msg)", "Suppliers", "$var(Suppliers)");
json_get_field("$evapi(msg)", "Error", "$var(Error)");
$var(id_index) = $(var(TransactionIndex){s.int});
$var(id_label) = $(var(TransactionLabel){s.int});
$var(CgrMaxSessionTime) = $(var(MaxSessionTime){s.int});
@@ -71,8 +102,8 @@ route[CGR_AUTH_REPLY] {
# 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)");
json_get_field("$evapi(msg)", "HashId", "$var(HashId)");
son_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,"})]}');
#$jsonrpl($var(reply));
}

View File

@@ -18,6 +18,12 @@ 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 ########
@@ -97,6 +103,7 @@ event_route[htable:mod-init] {
$sht(users=>1002) = "CGRateS.org";
$sht(users=>1003) = "CGRateS.org";
$sht(users=>1004) = "CGRateS.org";
$sht(users=>1005) = "CGRateS.org";
$sht(users=>1006) = "CGRateS.org";
$sht(users=>1007) = "CGRateS.org";
}
@@ -182,6 +189,7 @@ request_route {
$dlg_var(cgrAccount) = $fU;
$dlg_var(cgrDestination) = $rU;
route(CGRATES_AUTH_REQUEST); # Will be answered in CGRATES_AUTH_REPLY
#route(CGRATES_LCR_REQUEST);
exit;
}

View File

@@ -99,7 +99,7 @@ func TestTutKamCallsRestartKam(t *testing.T) {
if !*testCalls {
return
}
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "restart", 1000); err != nil {
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "restart", 4000); err != nil {
t.Fatal(err)
}
}
@@ -595,6 +595,7 @@ func TestTutKamCallsStopPjsuaListener(t *testing.T) {
time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER
}
/*
func TestTutKamCallsStopCgrEngine(t *testing.T) {
if !*testCalls {
return
@@ -610,3 +611,4 @@ func TestTutKamCallsStopKam(t *testing.T) {
}
engine.KillProcName("kamailio", 1000)
}
*/

View File

@@ -903,6 +903,7 @@ func TestTutLocalCdrStatsAfter(t *testing.T) {
}
}
/*
func TestTutLocalStopCgrEngine(t *testing.T) {
if !*testLocal {
return
@@ -911,3 +912,4 @@ func TestTutLocalStopCgrEngine(t *testing.T) {
t.Error(err)
}
}
*/