opensips搭配rtpengine实现sip信令和rtp流的代理
opensips部署在内外网双网卡服务器上时,sip信令我们可以通过opensips的路由脚本来做内外网转发,但是,语音媒体无法直接送达到内网的freeswitch上,因为opensips本身并不会处理媒体方面的事情,所以我们还需要搭建一个连通内外网的媒体代理,常用的有rtpproxy、rtpengine等,下面我尝试的rtpengine的方式,有不正确的地方也欢迎大家指正和交流,有需要这方面的详细脚本或者其他配置的可以给我发邮件联系,aaa@qq.com,谢谢。
模型的示意图
从图中可以看出,做内外网的这种方式通话,其实差别只是在rtp流的走向,我们使用rtpengine的作用也是如此,它是在opensips中使用的时候会更改sdp信息中的媒体通信的ip和端口,从而实现了sip电话端和软交换端都将媒体流发送到rtpengine上,之后rtpengine会根据相应的逻辑做两侧的映射,至于sip信令方面直接在opensips中写路由转发即可。
首先需要单独安装rtpengine,安装方法请自行去官方查看。
之后启动rtpengine,此处需要说明的是,在我们的场景中rtpengine要监听内外网两侧,所以启动的配置参数需要特别指定
./rtpengine -p /var/run/rtpengine.pid -i priv/172.33.1.xx -i pub/12.xx.xxx.1 -n 172.33.1.xx:60000 -c 172.33.1.xx:60001 -m 50000 -M 55000 -f -E -L 7
具体每个参数的含义可以去官方查看,因为时间很久了我也不太记得了。。。priv和pub两个ip分属内外网两块网卡,后面的是端口范围。
接下来是在opensips的路由脚本中使用rtpengine
总的来说就是两个方法的使用
rtpengine_offer("$var(rtpengine_flags)");
rtpengine_answer("$var(rtpengine_flags)");
顺序是先offer再answer,但是两个动作并不是一起来做,
branch_route[rtpengine] {
resetbflag(sdp_offer);
if ( ds_is_in_list("$si", "", "1") ) {
$var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove address-family=IP4 out-iface=pub in-iface=pub";
} else {
$var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove address-family=IP4 in-iface=priv out-iface=prive";
}
if ( (is_method("INVITE") || is_method("ACK") || is_method("PRACK")) && has_body("application/sdp") ) {
if( is_method("ACK") || is_method("PRACK") ) {
rtpengine_answer("$var(rtpengine_flags)");
} else {
rtpengine_offer("$var(rtpengine_flags)");
setbflag(sdp_offer);
}
}
}
一般是会先判断信令的来源是内网向外网发出还是外网向内网发出,以便赋值我们想要改变的sdp的内容。
这种分支路由我是在主路由开始就会走一遍,但是经过测试会发现有时会有漏掉的场景,所以在我们的真正转发INVITE信令的子路由中,定义t_on_reply("reply")路由,在t_on_reply("reply")路由中再做一次类似上面的offer和answer,但是判断条件就不是判断信令的method了,判断状态码即可。
思路比较混乱,大家见谅。