Kamailio RPC和OpenSIPS MI

今天笔者来给大家讲一下KamailioRPC和OpenSIPSMI的一些小区别。

以查找注册用户的信息为例,Kamailio的命令如下:

kamcmd ul.lookup location 1001@192.168.100.173
{
        AoR: 1001
        Contacts: {
                Contact: {
                        Address: sip:1001@192.168.1.122:9999;transport=udp
                        Expires: 2949
                        Q: -1
                        Call-ID: 61A34281A03EAD774B7CE87E3D1C009B@192.168.100.173
                        CSeq: 2
                        User-Agent: Kapanga Softphone Desktop Windows 1.00/2180b+1654855613_88A4C2D0E069_0A002700000D_508492987BAA_508492987BAB_528492987BAA
                        Received: sip:192.168.1.122:9999
                        Path: [not set]
                        State: CS_SYNC
                        Flags: 0
                        CFlags: 64
                        Socket: udp:192.168.100.173:5060
                        Methods: 16383
                        Ruid: uloc-6350e6b4-70a-1
                        Instance: [not set]
                        Reg-Id: 0
                        Server-Id: 0
                        Tcpconn-Id: -1
                        Keepalive: 0
                        Last-Keepalive: 1666246840
                        KA-Roundtrip: 0
                        Last-Modified: 1666246840
                }
        }
}

而OpenSIPS的命令是:

opensips-cli -x mi ul_show_contact location 1001@192.168.100.173
DEBUG: Loaded module 'mi'
DEBUG: sent command ':opensips_fifo_reply_22563:{"jsonrpc": "2.0", "id": "21695", "method": "which", "params": []}'
DEBUG: reply file '/tmp/opensips_fifo_reply_22563'
DEBUG: running in non-interactive mode mi ul_show_contact ['location', '1001@192.168.100.173']
DEBUG: running command 'ul_show_contact' '['location', '1001@192.168.100.173']'
DEBUG: positional parameters are used
DEBUG: 0. ['location', '1001@192.168.100.173']
DEBUG: running command 'ul_show_contact' '['location', '1001@192.168.100.173']'
DEBUG: sent command ':opensips_fifo_reply_30177:{"jsonrpc": "2.0", "id": "16856", "method": "ul_show_contact", "params": ["location", "1001@192.168.100.173"]}'
DEBUG: reply file '/tmp/opensips_fifo_reply_30177'
{
    "AOR": "1001",
    "Contacts": [
        {
            "Contact": "sip:1001@192.168.1.122:9999;transport=udp",
            "ContactID": "3784999887725085067",
            "Expires": 2963,
            "Q": "",
            "Callid": "7922F7BEA5AB8F92EE0AA287B27AB56F@192.168.100.173",
            "Cseq": 2,
            "User-agent": "Kapanga Softphone Desktop Windows 1.00/2180b+1654855613_88A4C2D0E069_0A002700000D_508492987BAA_508492987BAB_528492987BAA",
            "Received": "sip:192.168.1.122:9999",
            "State": "CS_SYNC",
            "Flags": 0,
            "Cflags": "NAT",
            "Socket": "udp:192.168.100.173:5060",
            "Methods": 16383
        }
    ]
}

无论传递的参数还是返回的结果,二者都非常相似。

其中Cflags保存的是分支标志,上面的例子Kamailio的分支标志是64,一般在Kamailio.cfg的开头几行能找到这样的定义:

#!define FLB_NATB 6

这是处理用户注册的路由脚本:

route[REGISTRAR] {
	if (!is_method("REGISTER")) return;

	if(isflagset(FLT_NATS)) {
		setbflag(FLB_NATB);  /* 如果运行到这里,ul.lookup看到的Cflags就是64, 1左移6,正好是64*/
	}
	if (!save("location")) {
		sl_reply_error();
	}
	exit;
}

OpenSIPS的分支标志是字符串,处理用户注册的路由脚本一般是:

	if (nat_uac_test(23)) {
		if (is_method("REGISTER")) {
			fix_nated_register();
			setbflag("NAT");  /* 如果运行到这里,ul_show_contact看到的Cflags就是NAT */
		} else {
			fix_nated_contact();
			setflag("NAT");
		}
	}

对于Kamailio,Ruid是主键,而对于OpenSIPS,contact_id是主键。

Kamailio的usrloc模块可以配置KeepAlive参数,服务器周期性探测客户端是否在线,这样Contact里面多了几个跟KeepAlive有关的参数。OpenSIPS的usrloc模块暂时没有这个功能。

上面给的都是外部程序调用,但其实在路由脚本里面调用Kamailio的RPC或者OpenSIPS的MI,都是很方便的。下面给出例子:

kamailio.cfg:

	$var(aor) = $tU + "@" + $td;
	$var(req) = '{"jsonrpc":"2.0","method":"ul.lookup","params":["location", "$var(aor)"],"id":1}';
	jsonrpc_exec("$var(req)");
	xlog("code = $jsonrpl(code)\n");
	xlog("body = $jsonrpl(body)\n");

opensips.cfg:

	/* 需要loadmodule "mi_script.so" */
	/* 需要loadmodule "json.so",解析结果 */
	$var(aor) = $tU + "@" + $td;
	$avp(params) = $var(aor);
	$avp(params) = "location";
	mi("ul_show_contact", $var(data), $avp(params));
	xlog("data = $var(data)\n");

需要注意的是,avp变量是以堆栈形式保存数据的,因此aor要放前面,接着是location,传到usrloc模块进行处理的时候参数正好反过来,location在前,aor在后。

以上代码在Kamailio5.5.5和OpenSIP3.2.8下测试通过。