Kamailio 的两种计费机制
Kamailio 计费模块支持两种计费机制,实现对计费事件的写入:
通过给 SIP 事务打上特殊标记,当该事务完成时将会写入计费事件(即,发送给上游的SIP响应代码大于或等于200)
通过执行由 acc 模块导出的函数,由配置文件脚本配置,在任何时候都可以立即写入计费事件
下面,我们分别介绍这两种计费机制。
通过标识方式计费
默认配置文件使用基于标识的机制进行计费。这里的第一步是通过模块参数告诉 acc 标识的值。配置文件可以通过不同的参数支持每个存储后台。
log_flag-
指定用于标记事务以进行日志计费的标志。db_flag-
指定用于标记数据库计费事务的标志。radius_flag-
指定用于标记radius计费的标志。
当使用相同的标识时,系统会将计费事件写入多个后端。带此标识的事务仅在响应代码为200-299
响应时进行计费。如果要在事务失败的情况下进行计费,必须设置另一个标志,该标志由参数failed_transaction_flag
指定。
Kamailio 的默认配置文件会将计费记录间接写入syslog
,并提供通过预处理器指令WITH_ACCDB
启用将计费记录写入数据库的选项。相关的配置文件部分如下所示:
....
1. #!define FLT_ACC 1
2. #!define FLT_ACCMISSED 2
3. #!define FLT_ACCFAILED 3
...
332.modparam("acc","log_flag", FLT_ACC)
...
1. #!ifdef WITH_ACCDB
340.modparam("acc","db_flag", FLT_ACC)
实际上,标记 1 用于记录成功的交易,标记 3 用于记录失败的交易(标记3不能单独使用,在这种情况下必须同时设置标记 1 )。
Flag 2 用于存储本地用户未接来电的详细信息,当呼出时是基于本地位置查询时才启用这个标识。
默认配置文件还提供了 MySQL 的 SQL 语句,用于创建acc
和missed_calls
表的列。如果用户使用向导安装了 Siremis 界面配置的话,则不需要执行 SQL 语句,因为向导配置已经完成了 SQL 语句执行。接下来的是默认配置文件中的部分,解释了启用计费和在数据库表中创建额外列的操作。
# *** To enhance accounting execute:
# - enable mysql
# - define WITH_ACCDB
# - add following columns to database
#!ifdef ACCDB_COMMENT
ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';
ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';
ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
#!endif
计费标记已设置为:
初始
INVITE
请求(仅标记已接听的电话的详细信息,分别接收 200 ok 响应)。BYE
请求(标记为存储所有BYE事务的记录,包括那些没有得到 200 ok 响应的事务 - 在这种情况下,当一个呼叫人的网络连接突然中断时,来自另一方的BYE就不会得到 200 ok ,但用户仍然希望记录这些数据以便能够获取 CDR )。初始
INVITE
请求在用户位置查找后发送(这次标记为存储未接来电的详细信).
接下来是默认配置文件中相关的代码片段,其中重点标识了 setflag 的操作。
493.
494. # account only INVITEs
495.if(is_method("INVITE")){
496.setflag(FLT_ACC); # 这里,do accounting
497.}
498.
…
592.if(is_method("BYE")){
593.setflag(FLT_ACC); # 这里,do accounting ...
594.setflag(FLT_ACCFAILED); # 这里 ... even if the transaction fails
595.}
…
676.
677. # when routing via usrloc, log the missed calls also
678.if(is_method("INVITE")){
679.setflag(FLT_ACCMISSED);// 这里
680.}
用户使用 Siremis 安装向导创建的 MYSQL 存储流程kamailio_cdrs()
,可以将INVITE
记录和BYE
记录的详细信息合并到一个通话数据记录中。本章稍后将详细介绍此过程。
使用计费模块函数写入数据
对于每个存储后端来说,acc 模块都会导出一个函数来写入计费信息。考虑在本书中,我们仅专注于将计费信息写入 syslog 和数据库,因此相应的函数是:
acc_log_request(comment)
acc_db_request(comment,table)
参数comment
是由配置文件设置的文本。它们以三位数字开头,则其值分为两部分,第一部分保存为 SIP 响应代码,第二部分保存为 SIP 响应原因文本。
table 参数表示要保存计费记录的数据库表的名称。该参数可以是动态字符串(包含的变量在运行时进行判断)。与使用标志时存储的详细信息相比,以表的形式存储时,这里部分值是不同:
在执行时被记录时间戳,不再等待 SIP 响应
SIP 响应代码来自于函数参数(如果参数“注释以3位数字开头,后跟空格”)
SIP 响应原因文本来自于函数参数(当值匹配此模式时-参数“注释”除了前三个数字和后面的空格外的值)。
这些函数可用于 SIP 请求和响应,从已处理的 SIP 消息及其事务上下文中获取值。这里提供一个示例来说明通过调用计费函数来替换BYE的基于标识的计费机制:
592. if (is_method("BYE")) {
593. acc_log_request(“210 Bye received”); # do accounting to syslog
594. acc_db_request(“210 Bye received”, “acc”); # do accounting to database
595. }
当收到BYE
时,记录被存储,因此不再担心无法得到响应。这些功能可用于写入同一事务中各种事件的计费记录。即使有许多 acc 模块参数可以自动记录早期媒体响应、ACK 或 CANCEL 请求,这些函数也可以让配置文件开发人员完全掌控何时执行它们。某些环境下,用户需要提供为计费或以统计为目的输出结果:
在收到初始的
INVITE
时的数据在初始
INVITE
请求被发送时的数据当收到第一个临时响应时的数据
收到铃声响应时的数据
例如,需要以上数据计算 PDD 呼叫方拨号后的延迟时间(PDD),PDD 是一个呼叫方在发送初始的INVITE
之后和呼叫方收到对端响应(振铃音或者忙音响应)之间的一个时间差。