diff --git a/data/tutorials/fs_evsock/cgrates/etc/cgrates/cdrc_fs.json b/data/tutorials/fs_evsock/cgrates/etc/cgrates/cdrc_fs.json new file mode 100644 index 000000000..f56c72677 --- /dev/null +++ b/data/tutorials/fs_evsock/cgrates/etc/cgrates/cdrc_fs.json @@ -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}, + ], + }, +}, + +} + diff --git a/data/tutorials/fs_evsock/cgrates/etc/init.d/cgrates b/data/tutorials/fs_evsock/cgrates/etc/init.d/cgrates index 5f13fdf76..9e4230c92 100755 --- a/data/tutorials/fs_evsock/cgrates/etc/init.d/cgrates +++ b/data/tutorials/fs_evsock/cgrates/etc/init.d/cgrates @@ -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 diff --git a/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json b/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json index 5bb64b85c..d8eb3d43b 100644 --- a/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json +++ b/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json @@ -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 + "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. -// "cdr_format": "csv", // CDR file format -// "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. +// "cdr_format": "csv", // CDR file format +// "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}, // ], -// } +// }, //}, diff --git a/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg b/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg index 4ca8454c2..954034144 100644 --- a/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg +++ b/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg @@ -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)); } diff --git a/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg b/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg index 2028b4be1..6ae550efd 100644 --- a/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg +++ b/data/tutorials/kamevapi/kamailio/etc/kamailio/kamailio.cfg @@ -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; } diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go index 399a948cd..3136dcc22 100644 --- a/general_tests/tutorial_kam_calls_test.go +++ b/general_tests/tutorial_kam_calls_test.go @@ -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) } +*/ diff --git a/general_tests/tutorial_local_test.go b/general_tests/tutorial_local_test.go index c15b30e22..9ce4a3ed7 100644 --- a/general_tests/tutorial_local_test.go +++ b/general_tests/tutorial_local_test.go @@ -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) } } +*/