1 RTPProxy服务安装和启动
#源码安装
git clone -b master https://github.com/sippy/rtpproxy.git
git -C rtpproxy submodule update --init --recursive
cd rtpproxy
./configure
make clean all
make install
#服务启动
# -l 对外的地址
# -s 后面的参数就是kamailio/opensips配置的rtpproxy_socket
rtpproxy -l 192.168.1.100 -s udp:192.168.1.100:7722
2 kamailio的rtpproxy模块
2.1 描述
- rtpproxy模块可以支持多个rtpproxy,用于平衡/分发、控制/选择目的
- 允许定义几组rtpproxy。负载平衡将在一个集上执行,管理员可以选择应该使用的集合。集合是通过它的id来选择的——id是由集合定义的
- rtpproxy模块根据集合中每个rtpproxy的权重自动完成集合内的平衡
- 集合的选择是在使用unforce_rtp_proxy(), rtpproxy_offer()或rtpproxy_answer()函数之前从脚本中完成
特别说明:如果有多个集合,则在调用rtpproxy_offer()/rtpproxy_answer()和unforce_rtpproxy()等方法时要使用相同的集合。
2.2 模块参数
参数名 |
类型 |
说明和示例 |
rtpproxy_sock |
string |
可以是单个socket udp:localhost:12221 也可以是一组sockert,默认集合是0 udp:localhost:12221 udp:localhost:12222 也可以指定集合id,应 “id==”指定 1 == udp:localhost:12221 udp:localhost:12222 |
rtpproxy_disable_tout |
integer |
默认60, 当RTPProxy 无法访问并标记为禁用 |
rtpproxy_tout |
integer |
默认1, 等待rtpproxy回复的超时时间 |
rtpproxy_retr |
integer |
默认5, 重试次数 |
nortpproxy_str |
string |
默认值为“a=nortpproxy:yes\r\n” 设置到sdp属性里,标记已经被更改 |
timeout_socket |
string |
默认控 发给rtpproxy,rtpproxy用来做重传 |
ice_candidate_priority_avp |
string |
|
extra_id_pv |
string |
|
db_url |
string |
数据库url(当设置了此参数,rtpproxy_sock参数将失效) 用来加载rtpproxy数据, |
table_name |
string |
表名 |
rtp_inst_pvar |
string |
设置伪变量,如果设置了该参数,选中的rtpproxy的URL将存储在给定的变量中 |
2.3模块方法
方法名 |
参数 |
说明 |
set_rtp_proxy_set |
setid |
设置要使用的rtpproxy集合id |
unforce_rtp_proxy |
[flag] |
断开 |
rtpproxy_destroy |
同 unforce_rtp_proxy |
|
start_recording |
发送标记到RTPProxy,用来记录RTP Stream |
|
rtpproxy_offer |
[flag [,ipaddr]] |
重写SDP,让rtp流通过rtpproxy转发 在Invite时触发 |
rtpproxy_answer |
参数同rtpproxy_offer |
重写SDP,让rtp流通过rtpproxy转发 在200OK响应 |
rtpproxy_manage |
参数同rtpproxy_offer |
会自动选择需要执行的方法rtpproxy_offer、rtpproxy_answer、unforce_rtpproxy |
2.4 流程逻辑
- kamailio收到invite请求
- 调用rtpproxy服务,rtpproxy创建会话,返回接收地址和端口
- 将rtpproxy返回的地址和端口修改到sdp
- 将修改后的invite请求发送到设备
- kamailio收到200 OK响应
- 调用rtpproxy服务,将200 OK携带的发送地址和端口通知过去,返回rtpproxy转发出来的地址和端口
- 将返回的地址和端口修改到200 OK的sdp
- 将修改后的200 OK返回到invite方
2.5 关键方法使用说明
主要用到的几个方法是rtpproxy_manage、rtpproxy_answer、rtpproxy_offer,它们使用方式基本一致,且rtpproxy_manage会根据sip消息自动决定使用rtpproxy_answer还是rtpproxy_offer。所以主要以rtpproxy_manage为例说明。
rtpproxy_manage([flag [, ipaddr]])
带有2个可选参数
a. flag:只指定flag
b. flag,ipaddr:指定flag和ip地址(指定ip地址后,修改sdp时会强制用指定的ip)
2.5.1 flag参数解释
1:在向rtpproxy发送命令时,将第一个Via分支附加到Call-ID
2:在向rtpproxy发送命令时,将第二个Via分支附加到Call-ID
3:如果是request消息,在向rtpproxy发送命令时,将第一个Via分支附加到Call-ID;如果是reply消息,在向rtpproxy发送命令时,将第二个Via分支附加到Call-ID
a:表示对端不自持对称RTP,会自动设置r参数
b:在向rtpproxy发送命令时,将extra_id_pv变量的值附加到Call-ID,必须设置extra_id_pv变量,注意:b不能与1、2、3同时使用
l:强制“查找”,只有当相应的会话在rtpproxy中已经存在时才重写SDP
i/e:标志指定SIP消息的方向。i”表示内部网络(LAN),“e”表示外部网络(WAN)。使用时必须指定两个标志来定义传入网络和传出网络,且请求和响应必须一致。比如请求使用“ie”,那么响应必须也是“ie”,可以有以下组合:ie、ei、ii、ee
x:该标志是使用RTPProxy的“ie”或“ei”标志的快捷方式,以便在“内部网络”的IPv4和“外部 网络”的IPv6之间自动桥接。区别是由SDP中给定的IP完成的,例如,IPv4地址将始终调用“ie”到RTPProxy (IPv4(i)到IPv6(e)),而IPv6Address将始终调用“ei”到RTPProxy (IPv6(e)到IPv4(i))
f:告诉rtpproxy忽略正在传输中的另一个rtpproxy插入的标记,以指示会话已经通过另一个代理
r:标记sdp内的地址有效,如果没有这个参数,则默认使用sip消息的源地址作为媒体地址
c:修改session的c字段的ip
w:接收消息的UA,必须强制支持对称RTP
z:修改payload大小
2.6 脚本示例
#加载rtpproxy模块
loadmodule "rtpproxy.so"
#设置rtpproxy_sock,也可以通过加载rtpproxy数据库来设置
modparam("rtpproxy", "rtpproxy_sock", "udp:192.168.1.100:7722")
request_route {
if(is_method("REGISTER"))
{
...
}
else
{
...
#收到非register请求时,尝试判断触发RTPPROXY
if (is_method("INVITE|UPDATE")) {
route(RTPROXY);
}
}
route(RELAY);
return;
}
route[RELAY] {
if (is_method("INVITE|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;
}
route[RTPROXY] {
#触发rtpproxy,模块内部会根据sip消息内容自动选择rtpproxy_offer、rtpproxy_answer或者执行
# 参数 “r”,会使用sdp里的地址
rtpproxy_manage("r");
return;
}
# Manage incoming replies in transaction context
onreply_route[MANAGE_REPLY] {
#成功触发
if(status=~"[12][0-9][0-9]") {
route(RTPROXY);
}
return;
}
# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
#失败触发
route(RTPROXY);
return;
}
2.7 抓包和截图
与rtpproxy服务交互信令抓包:
sip信令抓包: