Automatic usage in case of Suppliers

This commit is contained in:
DanB
2018-02-07 09:49:03 +01:00
parent 7509fe77b2
commit a617484722
10 changed files with 11 additions and 740 deletions

View File

@@ -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)) {

View File

@@ -1,4 +0,0 @@
#!/bin/sh
echo Firing up CGRateS engine
exec setuidgid cgrates /usr/bin/cgr-engine -config /etc/cgrates/cgrates.cfg

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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\"}");
}

View File

@@ -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;
}
}

View File

@@ -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{

View File

@@ -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"}}}