分享cgrates的kamailio脚本

通过evapi模块在对话开始和对话结束时发送cdr信息

kamailio.cfg

#!KAMAILIO

# Sample demo config for Kamailio-CGRateS communication
# tested against Kamailio 5.1

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

listen=udp:enp0s3:5060
listen=udp:127.0.0.1:5080
listen=udp:127.0.0.1:5060
listen=udp:enp0s3:5080

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 "jsonrpcs.so"



# ----------------- setting module-specific parameters ---------------

modparam("evapi", "bind_addr", "127.0.0.1:8448")

# ----- 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", "cgrconn=>size=1;")

####### Routing Logic ########

include_file "kamailio-cgrates.cfg"


# 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();

	# 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

	# SIMPLE AUTH methods
	if is_method("REGISTER|SUBSCRIBE|PUBLISH") {
		route(CGRATES_SIMPLEAUTH_REQUEST);
		exit;
	}

	if ($rU==$null) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}

	if !is_method("INVITE") {
		sl_send_reply("503", "Unsupported method");
                exit;
        }

	route(CGRATES_SESSIONAUTH_REQUEST);
	exit;
}


# Here will land requests after processing them with CGRateS.
route[CGRATES_SIMPLEAUTH_REPLY] {
        if $var(cgrError) != "" {
                xlog("CGR_PROFILE_ERROR: $var(cgrError)");
                sl_send_reply("503","CGR_ERROR");
                exit;
        }

	# parse the CGRateS attributes
	route(PARSE_CGRATES_ATTRIBUTES);

        # password based auth
        route(AUTH);

        if is_method("REGISTER") {
                route(REGISTRAR);
                exit;
        }

        # other methods going over location
        route(LOCATION);
        route(RELAY);
}


# Here will land requests after processing them with CGRateS. Call RELAY or other routes following this route
route[CGRATES_SESSIONAUTH_REPLY] {

	if $var(cgrError) != "" {
		xlog("CGR_AUTH_ERROR: $var(cgrError)");
		sl_send_reply("503","CGR_ERROR");
		exit;
	}

	 # parse the CGRateS attributes
        route(PARSE_CGRATES_ATTRIBUTES);

        # password based auth
        route(AUTH);

	# track the dialog so we can set it's timeout and channel variables to store in CDRs
	# cannot initialize the dialog sooner due to AUTH
	dlg_manage();
	$dlg_var(SetupTime) = $TS;
        $dlg_var(cgrOriginID) = $dlg(callid) + ";" + $dlg(from_tag);
	$dlg_var(cgrTenant) = "cgrates.org";
	$dlg_var(cgrReqType) = $avp(RequestType);
        $dlg_var(cgrAccount) = $fU;
        $dlg_var(cgrDestination) = $rU;
	$dlg_var(paypalAccount) = $avp(PaypalAccount);

	if $var(cgrMaxUsage) == 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(cgrMaxUsage)") {
		sl_send_reply("503","CGR_MAX_USAGE_ERROR");
		exit;
	}

	if $var(cgrRoutes) != "" { # Enforce the route variable to the first one received from CGRateS, here more for demo purposes
		$dlg_var(cgrRoutes) = $(var(cgrRoutes){s.select,0,,});
	}

	# user location service
	route(LOCATION);

	# send out
	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(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", "$avp(Password)", "0") ) {
			www_challenge("$td", "0");
			exit;
		}
	} else { # All other methods here
		if ( strempty($au) || !pv_proxy_authenticate("$td", "$avp(Password)", "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;
	}
}

kamailio-cgrates.cfg

# 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);
}

# Parse the CGRateS attributes from encoded variable into pseudovariables
route[PARSE_CGRATES_ATTRIBUTES] {
        # convert encoded attributes into individual Kamailio pseudovariables
        $var(idx) = 0;
        while !strempty($(var(cgrAttributes){s.select,$var(idx),,})) {
                $avp($(var(cgrAttributes){s.select,$var(idx),,}{s.select,0,:}))
                        = $(var(cgrAttributes){s.select,$var(idx),,}{s.select,1,:});
                $var(idx) = $var(idx) + 1;
        }
}


# 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,"})]}');
}

route[CGR_DLG_LIST] {
 if $sht(cgrconn=>cgr) == $null {
                sl_send_reply("503","Charging controller unreachable");
                exit;
        }
        jsonrpc_exec('{"jsonrpc":"2.0","id":1, "method":"dlg.list","params":[]}');
		evapi_relay("{\"event\":\"CGR_DLG_LIST_REPLY\",
			\"jsonrpl_body\":$jsonrpl(body)}");
}


# Route to mainly query account password from CGRateS
route[CGRATES_SIMPLEAUTH_REQUEST] {
	 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_flags\":\"*attributes\",
		\"cgr_context\":\"simpleauth\",
		\"reply_route\":\"CGR_SIMPLEAUTH_REPLY\",
		\"Account\":\"$fU\"}");
}


# Route receiving simpleauth replies, sanitizes them and dispatch back into Kamailio inside CGRATES_SIMPLEAUTH_REPLY
route[CGR_SIMPLEAUTH_REPLY] {

	json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)");
        $var(TransactionIndex) = $(var(TransactionIndex){s.rm,"});
        $var(id_index) = $(var(TransactionIndex){s.int});

        json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
        $var(TransactionLabel) = $(var(TransactionLabel){s.rm,"});
        $var(id_label) = $(var(TransactionLabel){s.int});

        json_get_field("$evapi(msg)", "Attributes", "$var(cgrAttributes)");
	$var(cgrAttributes) = $(var(cgrAttributes){s.rm,"});

	json_get_field("$evapi(msg)", "Error", "$var(cgrError)");
        $var(cgrError) = $(var(cgrError){s.rm,"});

        t_continue("$var(id_index)", "$var(id_label)", "CGRATES_SIMPLEAUTH_REPLY"); # Unpark the transaction

}


# Request session auth information from CGRateS
route[CGRATES_SESSIONAUTH_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_flags\":\"*attributes;*accounts;*routes;*resources;*thresholds\",
		\"reply_route\":\"CGR_SESSIONAUTH_REPLY\",
		\"Account\":\"$fU\",
		\"Destination\":\"$rU\",
		\"SetupTime\":\"$TS\"}");
}


# Process SESSIONAUTH_reply from CGRateS
route[CGR_SESSIONAUTH_REPLY] {
	json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)");
	$var(TransactionIndex) = $(var(TransactionIndex){s.rm,"});
	$var(id_index) = $(var(TransactionIndex){s.int});

	json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)");
	$var(TransactionLabel) = $(var(TransactionLabel){s.rm,"});
	$var(id_label) = $(var(TransactionLabel){s.int});

	json_get_field("$evapi(msg)", "Attributes", "$var(cgrAttributes)");
	$var(cgrAttributes) = $(var(cgrAttributes){s.rm,"});
	
	json_get_field("$evapi(msg)", "ResourceAllocation", "$var(cgrResourceAllocation)");
	$var($var(cgrResourceAllocation)) = $(var(cgrResourceAllocation){s.rm,"});

	json_get_field("$evapi(msg)", "MaxUsage", "$var(MaxUsage)");
	$var(cgrMaxUsage) = $(var(MaxUsage){s.int});

	json_get_field("$evapi(msg)", "Routes", "$var(cgrRoutes)");
	$var($var(cgrRoutes)) = $(var(cgrRoutes){s.rm,"});

	json_get_field("$evapi(msg)", "Error", "$var(cgrError)");
	$var(cgrError) = $(var(cgrError){s.rm,"});

	t_continue("$var(id_index)", "$var(id_label)", "CGRATES_SESSIONAUTH_REPLY"); # Unpark the transaction 
}


# 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\",
		\"h_entry\":\"$dlg(h_entry)\",
		\"h_id\":\"$dlg(h_id)\",
		\"cgr_flags\":\"*attributes;*accounts;*resources;*thresholds\",
		\"OriginID\":\"$dlg_var(cgrOriginID)\",
		\"RequestType\":\"$dlg_var(cgrReqType)\",
		\"Tenant\":\"$dlg_var(cgrTenant)\",
		\"Account\":\"$dlg_var(cgrAccount)\",
		\"Destination\":\"$dlg_var(cgrDestination)\",
		\"SetupTime\":\"$dlg_var(SetupTime)\",
		\"AnswerTime\":\"$TS\"}");
}


# 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\",
		\"cgr_flags\":\"*accounts;*resources\",
		\"OriginID\":\"$dlg_var(cgrOriginID)\",
		\"RequestType\":\"$dlg_var(cgrReqType)\",
		\"Tenant\":\"$dlg_var(cgrTenant)\",
		\"Account\":\"$dlg_var(cgrAccount)\", 
		\"Destination\":\"$dlg_var(cgrDestination)\",
		\"AnswerTime\":\"$dlg(start_ts)\",
		\"PaypalAccount\":\"$dlg_var(paypalAccount)\",
		\"SetupTime\":\"$dlg_var(SetupTime)\",
		\"Usage\":\"$var(callDur)\"}");
}

cgrates/data/tutorials/kamevapi at master · cgrates/cgrates · GitHub

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kamailio是一款开源的SIP服务器,它可以用于构建大规模的VoIP和实时通信系统。在Linux上安装Kamailio非常简单,只需按照以下步骤操作: 1. 安装依赖项 在安装Kamailio之前,您需要安装一些必需的依赖项。在Ubuntu上,您可以使用以下命令安装它们: ``` sudo apt-get update sudo apt-get install -y git-core make bison flex gcc pkg-config libncurses5-dev libreadline-dev libssl-dev libxml2-dev libdb-dev libcurl4-openssl-dev libpcre3-dev libjson-c-dev libyaml-dev libz-dev ``` 2. 下载Kamailio 您可以从Kamailio的官方网站下载最新版本的源代码。解压缩下载的文件并进入目录: ``` tar -xzf kamailio-x.y.z.tar.gz cd kamailio-x.y.z ``` 3. 编译和安装Kamailio 使用以下命令编译和安装Kamailio: ``` make cfg make all sudo make install ``` 4. 配置Kamailio Kamailio的配置文件位于`/usr/local/etc/kamailio/kamailio.cfg`。您可以使用任何文本编辑器打开并编辑此文件以配置Kamailio。 5. 启动Kamailio 使用以下命令启动Kamailio: ``` sudo kamailio -f /usr/local/etc/kamailio/kamailio.cfg ``` 如果您想将Kamailio作为系统服务运行,则可以将以下内容添加到`/etc/systemd/system/kamailio.service`文件中: ``` [Unit] Description=Kamailio SIP Server After=syslog.target network.target [Service] Type=forking PIDFile=/var/run/kamailio.pid ExecStart=/usr/local/sbin/kamailio -P /var/run/kamailio.pid -f /usr/local/etc/kamailio/kamailio.cfg ExecReload=/bin/kill -s HUP $MAINPID [Install] WantedBy=multi-user.target ``` 然后,使用以下命令启动Kamailio服务: ``` sudo systemctl start kamailio ``` 这就是在Linux上安装Kamailio的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值