mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-15 05:09:54 +05:00
Automatic usage in case of Suppliers
This commit is contained in:
@@ -132,14 +132,15 @@ func radPassesFieldFilter(pkt *radigo.Packet, processorVars processorVars,
|
||||
}
|
||||
|
||||
// radComposedFieldValue extracts the field value out of RADIUS packet
|
||||
// procVars have priority over packet variables
|
||||
func radComposedFieldValue(pkt *radigo.Packet,
|
||||
processorVars processorVars, outTpl utils.RSRFields) (outVal string) {
|
||||
procVars processorVars, outTpl utils.RSRFields) (outVal string) {
|
||||
for _, rsrTpl := range outTpl {
|
||||
if rsrTpl.IsStatic() {
|
||||
outVal += rsrTpl.ParseValue("")
|
||||
continue
|
||||
}
|
||||
if val, err := processorVars.valAsString(rsrTpl.Id); err != nil {
|
||||
if val, err := procVars.valAsString(rsrTpl.Id); err != nil {
|
||||
if err.Error() != "not found" {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> %s",
|
||||
@@ -148,6 +149,7 @@ func radComposedFieldValue(pkt *radigo.Packet,
|
||||
}
|
||||
} else {
|
||||
outVal += rsrTpl.ParseValue(val)
|
||||
continue
|
||||
}
|
||||
for _, avp := range pkt.AttributesWithName(
|
||||
attrVendorFromPath(rsrTpl.Id)) {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
echo Firing up CGRateS engine
|
||||
exec setuidgid cgrates /usr/bin/cgr-engine -config /etc/cgrates/cgrates.cfg
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<configuration name="cdr_csv.conf" description="CDR CSV Format">
|
||||
<settings>
|
||||
<!-- 'cdr-csv' will always be appended to log-base -->
|
||||
<!--<param name="log-base" value="/var/log"/>-->
|
||||
<param name="default-template" value="example"/>
|
||||
<!-- This is like the info app but after the call is hung up -->
|
||||
<!--<param name="debug" value="true"/>-->
|
||||
<param name="rotate-on-hup" value="true"/>
|
||||
<!-- may be a b or ab -->
|
||||
<param name="legs" value="a"/>
|
||||
<!-- Only log in Master.csv -->
|
||||
<!-- <param name="master-file-only" value="true"/> -->
|
||||
</settings>
|
||||
<templates>
|
||||
<template name="sql">INSERT INTO cdr VALUES ("${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}", "${accountcode}");</template>
|
||||
<template name="example">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}"</template>
|
||||
<template name="snom">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}", "${accountcode}","${read_codec}","${write_codec}","${sip_user_agent}","${call_clientcode}","${sip_rtp_rxstat}","${sip_rtp_txstat}","${sofia_record_file}"</template>
|
||||
<template name="linksys">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}","${sip_user_agent}","${sip_p_rtp_stat}"</template>
|
||||
<template name="asterisk">"${accountcode}","${caller_id_number}","${destination_number}","${context}","${caller_id}","${channel_name}","${bridge_channel}","${last_app}","${last_arg}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${amaflags}","${uuid}","${userfield}"</template>
|
||||
<template name="opencdrrate">"${uuid}","${signal_bond}","${direction}","${ani}","${destination_number}","${answer_stamp}","${end_stamp}","${billsec}","${accountcode}","${userfield}","${network_addr}","${regex('${original_caller_id_name}'|^.)}","${sip_gateway_name}"</template>
|
||||
</templates>
|
||||
</configuration>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<configuration name="json_cdr.conf" description="JSON CDR">
|
||||
<settings>
|
||||
|
||||
<!-- Global parameters -->
|
||||
<param name="log-b-leg" value="false"/>
|
||||
<param name="prefix-a-leg" value="false"/>
|
||||
|
||||
<!-- Whether to URL encode the individual JSON values. Defaults to true, set to false for standard JSON. -->
|
||||
<param name="encode-values" value="false"/>
|
||||
|
||||
<!-- Normally if url and log-dir are present, url is attempted first and log-dir second. This options allows to do both systematically. -->
|
||||
<param name="log-http-and-disk" value="false"/>
|
||||
|
||||
<!-- File logging -->
|
||||
<!-- Directory where to create the "json_cdr" directory used to store JSON CDRs. Leave empty for no file logging. -->
|
||||
<!-- Might be overriden by a channel variable "json_cdr_base". -->
|
||||
<param name="log-dir" value=""/>
|
||||
<!-- Whether to rotate file CDRs. -->
|
||||
<param name="rotate" value="false"/>
|
||||
|
||||
<!-- HTTP(S) logging -->
|
||||
<!-- URL where to POST JSON CDRs. Leave empty for no URL logging. Up to 20 URLs may be specified. -->
|
||||
<param name="url" value="http://127.0.0.1:2080/freeswitch_json"/>
|
||||
<!-- Authentication scheme for the above URL. May be one of basic|digest|NTLM|GSS-NEGOTIATE|any-->
|
||||
<param name="auth-scheme" value="basic"/>
|
||||
<!-- Credentials in the form usernameassword if auth-scheme is used. Leave empty for no authentication. -->
|
||||
<param name="cred" value="string"/>
|
||||
<!-- Whether to base64 encode the entire JSON document before POSTing it. -->
|
||||
<param name="encode" value="base64|true|false"/>
|
||||
<!-- Number of retries in case of failure. Each specified URL is tried in turn. -->
|
||||
<param name="retries" value="0"/>
|
||||
<!-- Delay between retries (ms). -->
|
||||
<param name="delay" value="5000"/>
|
||||
<!-- Disable streaming if the server doesn't support it. -->
|
||||
<param name="disable-100-continue" value="false"/>
|
||||
<!-- If web posting failed, the CDR is written to a file. -->
|
||||
<!-- Error log dir ("json_cdr" is appended). Up to 20 may be specified. Default to log-dir if none is specified. -->
|
||||
<param name="err-log-dir" value=""/>
|
||||
|
||||
|
||||
<!-- SSL options -->
|
||||
<param name="ssl-key-path" value=""/>
|
||||
<param name="ssl-key-password" value=""/>
|
||||
<!-- SSL version. If specified, must be either "SSLv3" or "TLSv1". -->
|
||||
<param name="ssl-version" value=""/>
|
||||
<param name="enable-ssl-verifyhost" value="false"/>
|
||||
<param name="ssl-cert-path" value=""/>
|
||||
<param name="enable-cacert-check" value="false"/>
|
||||
<param name="ssl-cacert-file" value=""/>
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -1,71 +0,0 @@
|
||||
<!--
|
||||
Exemplify the integration between CGRateS and FreeSWITCH.
|
||||
-->
|
||||
|
||||
<include>
|
||||
<context name="default">
|
||||
|
||||
<extension name="unloop">
|
||||
<condition field="${unroll_loops}" expression="^true$" />
|
||||
<condition field="${sip_looped_call}" expression="^true$">
|
||||
<action application="deflect" data="${destination_number}" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="call_debug" continue="true">
|
||||
<condition field="${call_debug}" expression="^true$" break="never">
|
||||
<action application="info" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!--- CGRateS related extensions -->
|
||||
<!-- Place all requests into park app. Notify must be empty so we do not loop. Order Lcr computation -->
|
||||
<extension name="CGRateS_Auth">
|
||||
<condition field="${cgr_notify}" expression="^$">
|
||||
<!---<action application="set" data="cgr_computelcr=true" />-->
|
||||
<action application="park" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- In case of CGRateS returning INSUFFICIENT_FUNDS, play the message (if recorded) and disconnect the call with 403. -->
|
||||
<extension name="CGRateS_AuthForbidden">
|
||||
<condition field="${cgr_notify}" expression="^-INSUFFICIENT_FUNDS$">
|
||||
<action application="set" data="proto_specific_hangup_cause=sip:403" />
|
||||
<action application="hangup" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- In case of CGRateS returning UNAUTHORIZED_DESTINATION, play the message (if recorded) and disconnect the call with 403. -->
|
||||
<extension name="CGRateS_AuthForbidden">
|
||||
<condition field="${cgr_notify}" expression="^-UNAUTHORIZED_DESTINATION$">
|
||||
<action application="set" data="proto_specific_hangup_cause=sip:403" />
|
||||
<action application="hangup" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- In case of CGRateS returning SYSTEM_ERROR, disconnect the call so we do not risk prepaid calls going out. -->
|
||||
<extension name="CGRateS_Error">
|
||||
<condition field="${cgr_notify}" expression="^-SYSTEM_ERROR$">
|
||||
<action application="set" data="proto_specific_hangup_cause=sip:503" />
|
||||
<action application="hangup" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- Use Suppliers information to simulate calls to suppliers, replace here with real gateway ids out of suppliers -->
|
||||
<extension name="CGR Suppliers">
|
||||
<condition field="cgr_suppliers" expression=".+">
|
||||
<action application="set" data="cgr_supplier=${cgr_suppliers[1]}" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- Connect call normally, it was not influenced so far by CGRateS -->
|
||||
<extension name="Local_Extension">
|
||||
<condition field="destination_number" expression="^(10[01][0-9])$">
|
||||
<action application="set" data="ringback=${us-ring}" />
|
||||
<action application="set" data="call_timeout=30" />
|
||||
<action application="bridge" data="user/${destination_number}@${domain_name}" />
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
</context>
|
||||
</include>
|
||||
@@ -1,28 +0,0 @@
|
||||
<!--
|
||||
CGRateS config sample.
|
||||
|
||||
Make default 1000 user prepaid by adding cgr_reqtype variable to your user.
|
||||
-->
|
||||
|
||||
<include>
|
||||
<user id="1000">
|
||||
<!-- CGRateS config sample.
|
||||
Make default 1000 user prepaid by adding cgr_reqtype variable to your user -->
|
||||
<params>
|
||||
<param name="password" value="$${default_password}"/>
|
||||
<param name="vm-password" value="1000"/>
|
||||
</params>
|
||||
<variables>
|
||||
<variable name="toll_allow" value="domestic,international,local"/>
|
||||
<variable name="accountcode" value="1000"/>
|
||||
<variable name="user_context" value="default"/>
|
||||
<variable name="effective_caller_id_name" value="Extension 1000"/>
|
||||
<variable name="effective_caller_id_number" value="1000"/>
|
||||
<variable name="outbound_caller_id_name" value="$${outbound_caller_name}"/>
|
||||
<variable name="outbound_caller_id_number" value="$${outbound_caller_id}"/>
|
||||
<variable name="callgroup" value="techsupport"/>
|
||||
<variable name="cgr_reqtype" value="*prepaid"/>
|
||||
</variables>
|
||||
</user>
|
||||
</include>
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
# 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);
|
||||
}
|
||||
|
||||
# Called by Kamailio on local disconnect
|
||||
event_route[tm:local-request] {
|
||||
route(CGR_CALL_END);
|
||||
}
|
||||
|
||||
|
||||
# Send AUTH_REQUEST to CGRateS
|
||||
route[CGRATES_AUTH_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_reqtype\":\"$dlg_var(cgrReqType)\",
|
||||
\"cgr_tenant\":\"$dlg_var(cgrTenant)\",
|
||||
\"cgr_account\":\"$dlg_var(cgrAccount)\",
|
||||
\"cgr_destination\":\"$dlg_var(cgrDestination)\",
|
||||
\"cgr_setuptime\":\"$TS\",
|
||||
\"cgr_computelcr\":\"true\"}");
|
||||
}
|
||||
|
||||
# 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)");
|
||||
$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});
|
||||
$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
|
||||
}
|
||||
|
||||
# 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,"})]}');
|
||||
#$jsonrpl($var(reply));
|
||||
}
|
||||
|
||||
# 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\",
|
||||
\"callid\":\"$dlg(callid)\",
|
||||
\"from_tag\":\"$dlg(from_tag)\",
|
||||
\"h_entry\":\"$dlg(h_entry)\",
|
||||
\"h_id\":\"$dlg(h_id)\",
|
||||
\"cgr_reqtype\":\"$dlg_var(cgrReqType)\",
|
||||
\"cgr_tenant\":\"$dlg_var(cgrTenant)\",
|
||||
\"cgr_account\":\"$dlg_var(cgrAccount)\",
|
||||
\"cgr_destination\":\"$dlg_var(cgrDestination)\",
|
||||
\"cgr_answertime\":\"$TS\",
|
||||
\"cgr_supplier\":\"$dlg_var(cgrSupplier)\"}");
|
||||
}
|
||||
|
||||
# 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\",
|
||||
\"callid\":\"$dlg(callid)\",
|
||||
\"from_tag\":\"$dlg(from_tag)\",
|
||||
\"cgr_reqtype\":\"$dlg_var(cgrReqType)\",
|
||||
\"cgr_tenant\":\"$dlg_var(cgrTenant)\",
|
||||
\"cgr_account\":\"$dlg_var(cgrAccount)\",
|
||||
\"cgr_destination\":\"$dlg_var(cgrDestination)\",
|
||||
\"cgr_answertime\":\"$dlg(start_ts)\",
|
||||
\"cgr_duration\":\"$var(callDur)\",
|
||||
\"cgr_supplier\":\"$dlg_var(cgrSupplier)\",
|
||||
\"cgr_disconnectcause\":\"$T_reply_code\"}");
|
||||
}
|
||||
|
||||
@@ -1,408 +0,0 @@
|
||||
#!KAMAILIO
|
||||
|
||||
####### 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
|
||||
|
||||
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 "xhttp.so"
|
||||
loadmodule "jsonrpc-s.so"
|
||||
|
||||
|
||||
|
||||
# ----------------- setting module-specific parameters ---------------
|
||||
|
||||
|
||||
# ----- 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", "users=>size=8;")
|
||||
modparam("htable", "htable", "cgrconn=>size=1;")
|
||||
|
||||
####### Routing Logic ########
|
||||
|
||||
include_file "kamailio-cgrates.cfg"
|
||||
|
||||
event_route[htable:mod-init] {
|
||||
$sht(users=>1001) = "CGRateS.org";
|
||||
$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";
|
||||
}
|
||||
|
||||
|
||||
# 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();
|
||||
|
||||
# authentication
|
||||
route(AUTH);
|
||||
|
||||
# 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
|
||||
|
||||
# handle registrations
|
||||
route(REGISTRAR);
|
||||
|
||||
if ($rU==$null) {
|
||||
# request with no Username in RURI
|
||||
sl_send_reply("484","Address Incomplete");
|
||||
exit;
|
||||
}
|
||||
|
||||
# user location service
|
||||
route(LOCATION);
|
||||
if !is_method("INVITE") {
|
||||
route(RELAY);
|
||||
}
|
||||
dlg_manage();
|
||||
switch ($fU) {
|
||||
case 1001:
|
||||
case 1006:
|
||||
case 1007:
|
||||
$dlg_var(cgrReqType) = "*prepaid";
|
||||
break;
|
||||
case 1002:
|
||||
$dlg_var(cgrReqType) = "*postpaid";
|
||||
break;
|
||||
case 1003:
|
||||
$dlg_var(cgrReqType) = "*pseudoprepaid";
|
||||
break;
|
||||
default:
|
||||
$dlg_var(cgrReqType) = "*rated";
|
||||
}
|
||||
$dlg_var(cgrTenant) = "cgrates.org";
|
||||
$dlg_var(cgrAccount) = $fU;
|
||||
$dlg_var(cgrDestination) = $rU;
|
||||
route(CGRATES_AUTH_REQUEST); # Will be answered in CGRATES_AUTH_REPLY
|
||||
#route(CGRATES_LCR_REQUEST);
|
||||
exit;
|
||||
}
|
||||
|
||||
# Here will land requests after processing them with CGRateS. Call RELAY or other routes following this route
|
||||
route[CGRATES_AUTH_REPLY] {
|
||||
if $var(CgrError) != "" {
|
||||
xlog("CGR_AUTH_ERROR: $var(CgrError)");
|
||||
sl_send_reply("503","CGR_ERROR");
|
||||
exit;
|
||||
}
|
||||
if $var(CgrMaxSessionTime) != -1 {
|
||||
if $var(CgrMaxSessionTime) == 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(CgrMaxSessionTime)") {
|
||||
sl_send_reply("503","CGR_MAX_SESSION_TIME_ERROR");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if $var(CgrSuppliers) != "" { # Enforce the supplier variable to the first one received from CGRateS, more for testing purposes
|
||||
$dlg_var(cgrSupplier) = $(var(CgrSuppliers){s.select,0,,});
|
||||
}
|
||||
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 (!is_method("REGISTER")) return;
|
||||
|
||||
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", "$sht(users=>$au)", "0") ) {
|
||||
www_challenge("$td", "0");
|
||||
exit;
|
||||
}
|
||||
} else { # All other methods here
|
||||
if ( strempty($au) || !pv_proxy_authenticate("$td", "$sht(users=>$au)", "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;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (spS *SupplierService) matchingSupplierProfilesForEvent(ev *utils.CGREvent)
|
||||
func (spS *SupplierService) costForEvent(ev *utils.CGREvent,
|
||||
acntIDs, rpIDs []string) (costData map[string]interface{}, err error) {
|
||||
if err = ev.CheckMandatoryFields([]string{utils.Account,
|
||||
utils.Destination, utils.SetupTime, utils.Usage}); err != nil {
|
||||
utils.Destination, utils.SetupTime}); err != nil {
|
||||
return
|
||||
}
|
||||
var acnt, subj, dst string
|
||||
@@ -180,9 +180,11 @@ func (spS *SupplierService) costForEvent(ev *utils.CGREvent,
|
||||
if sTime, err = ev.FieldAsTime(utils.SetupTime, spS.timezone); err != nil {
|
||||
return
|
||||
}
|
||||
var usage time.Duration
|
||||
if usage, err = ev.FieldAsDuration(utils.Usage); err != nil {
|
||||
return
|
||||
usage := time.Duration(time.Minute)
|
||||
if _, has := ev.Event[utils.Usage]; has {
|
||||
if usage, err = ev.FieldAsDuration(utils.Usage); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, anctID := range acntIDs {
|
||||
cd := &CallDescriptor{
|
||||
|
||||
@@ -35,6 +35,7 @@ func TestNewRSRField1(t *testing.T) {
|
||||
}
|
||||
// With filter
|
||||
rulesStr = `~sip_redirected_to:s/sip:\+49(\d+)@/0$1/(086517174963)`
|
||||
// rulesStr = `~sip_redirected_to:s/sip:\+49(\d+)@/0$1/{*usage_seconds;*round:5:*middle}(086517174963)`
|
||||
filter, _ := NewRSRFilter("086517174963")
|
||||
expRSRField2 := &RSRField{Id: "sip_redirected_to", Rules: rulesStr, filters: []*RSRFilter{filter},
|
||||
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`sip:\+49(\d+)@`), ReplaceTemplate: "0$1"}}}
|
||||
|
||||
Reference in New Issue
Block a user