背景
公司项目需要使用opensips作为sip协议网关, 使用中遇到一些难题, 分享给有需要的人
官网
https://www.opensips.org
建议先看官网, 搞不定了再百度
版本信息
3.1.3
问题点
- 编译报错
- 问题描述
pthread_xxx相关的一些实现找不到 - 报错信息
main.o: In function
pthread_mutex_init': /opt/opensips-3.1.3/ssl_tweaks.h:32: undefined reference to
pthread_mutexattr_setpshared’
/opt/opensips-3.1.3/ssl_tweaks.h:26: undefined reference topthread_mutexattr_init' /opt/opensips-3.1.3/ssl_tweaks.h:32: undefined reference to
pthread_mutexattr_setpshared’
/opt/opensips-3.1.3/ssl_tweaks.h:38: undefined reference topthread_mutexattr_destroy' main.o: In function
pthread_rwlock_init’:
/opt/opensips-3.1.3/ssl_tweaks.h:64: undefined reference topthread_rwlockattr_setpshared' /opt/opensips-3.1.3/ssl_tweaks.h:58: undefined reference to
pthread_rwlockattr_init’
/opt/opensips-3.1.3/ssl_tweaks.h:64: undefined reference topthread_rwlockattr_setpshared' /opt/opensips-3.1.3/ssl_tweaks.h:70: undefined reference to
pthread_rwlockattr_destroy’ - 解决方案
先执行export LDFLAGS=-lpthread
, 然后再执行make all
- 问题描述
- 用opensips-cli做sqlite数据库初始化报错[mysql没问题]
- 报错信息
ERROR: Bad database URL: sqlite:opt/opensips/opensips.db, missing host part
- opensips-cli配置文件
database_admin_url: sqlite:opt/opensips/opensips.db
database_modules: ALL
database_schema_path:/home/media_develop/third-party-src/opensips-3.1.3/scripts- 解决方案
直接用sqlite3来生成db文件, 不用opensips-cli, 命令中的xxx.sql文件在opensips源码路径中, 根据自己的环境来写命令, 我的源码在/home/media_develop/third-party-src/opensips-3.1.3
, 此处命令我只创建了standard-create.sql + dispatcher-create.sql, 如果有其他需求运行对应的xxx-create.sqlsqlite3指令如果不存在自己装一下
yum install sqlite-devel
orapt install -y sqlite3
sqlite3 opensips.db < /home/media_develop/third-party-src/opensips-3.1.3/scripts/sqlite/standard-create.sql sqlite3 opensips.db < /home/media_develop/third-party-src/opensips-3.1.3/scripts/sqlite/dispatcher-create.sql
分享经验
1. 编译opensips带上sqlite模块
官网sqlite模块有介绍
from command line use: ‘make all include_modules=“db_sqlite”; make install include_modules=“db_sqlite”’;
2. 配置编译选项–module选择
- 打开配置页面
make menuconfig
方向键上下选择, 右打开子菜单/确认, 左返回上一级, 按下键盘h查看帮助, 空格选中/取消选中
- 打开
Configure Compile Options
- 打开
Configure Excluded Modules
- 选中需要的模块
按空格就会有个*, 代表选中, 再用空格可以取消选中
- 返回上一层
- 选择
Save Changes
注意按方向右之后还要再按一次任意键为确认, 我一般就是再按一次方向右, 底部出现Press h for navigation help.
表示保存完成 - 返回上一层
- 选择
Compile And Install OpenSIPS
- 等待编译+安装
有很多编译选项, 可以自己每个点开看一下
请求分发
和负载均衡有点像, 但是opensips不记录任何信息, 单纯的做hash, 性能很好
1. 数据库配置
dispatcher表添加记录, 可以手动写入
2. 脚本编写
modparam("dispatcher", "ds_ping_method", "OPTIONS")
modparam("dispatcher", "ds_probing_mode", 1)
modparam("dispatcher", "ds_ping_interval", 10)
modparam("dispatcher", "hash_pvar", "$fU")
route
{
# 平台主动发起的请求
if($fU == "31000000002000000000")
{
# 代理给设备
t_relay();
#route(FORWARD);
exit();
}
else{
# 注册根据设备国标号分发
if(is_method("REGISTER"))
{
route(HASH_USER);
}
else if(is_method("MESSAGE"))
{
# 心跳根据设备国标号分发
if(search_body("Keepalive"))
{
route(HASH_USER);
}
# 目录可能有多种策略
# 1. 全部发送给请求的信令服务
# 2. 分发给不同的信令服务
else if(search_body('Catalog'))
{
route(BY_CALL_ID);
}
else
{
route(BY_CALL_ID);
}
}
# 设备发送的BYE需要根据CALL-ID路由
else if(is_method("BYE"))
{
route(BY_CALL_ID);
}
else
{
route(HASH_USER);
}
t_relay();
}
}
# 根据uri直接代理发送
route[FORWARD]
{
# forward according to uri
forward();
}
# 根据call-id代理给发送的信令服务
route[BY_CALL_ID]
{
route(HASH_USER);
}
# 根据发送方国标号分发请求
route[HASH_USER]
{
if(!ds_select_dst(1,7))
{
send_reply(503,"Service Unavailable");
}
}
# 根据SN代理给发送的信令服务
route[BY_SN]
{
route(HASH_USER);
}
- 使用OPTIONS请求探测信令服务状态, 配置文件设置的10秒间隔
- 使用From头中的User作为哈希参数来分发请求
- REGISTER和Keepalive请求的From User是一样的, 可以保证注册会话信息都分发给同一个sip服务器
- t_relay()很有用, 不能少, 用来把请求分发出去
3. 请求分发流程
192.168.33.189:5060
发起注册, 发给192.168.33.244:15061
192.168.33.244:15061
是opensips, 将请求代理给192.168.33.244:5061
192.168.33.244:5061
处理注册请求
对应报文:
# opensips收到的请求
REGISTER sip:31000000002000000000@3101120000 SIP/2.0
Via: SIP/2.0/UDP 192.168.33.189:5060;rport;branch=z9hG4bK927374352
From: <sip:31010500001320000000@3101120000>;tag=607068637
To: <sip:31010500001320000000@3101120000>
Call-ID: 998163489
CSeq: 1 REGISTER
Contact: <sip:31010500001320000000@192.168.33.189:5060>
Max-Forwards: 70
User-Agent: IP Camera
Expires: 3600
Content-Length: 0
# opensips把请求代理发送给192.168.33.244:5061
REGISTER sip:31000000002000000000@3101120000 SIP/2.0
Via: SIP/2.0/UDP 172.25.0.2:15061;branch=z9hG4bK25ec.99ec3542.0
Via: SIP/2.0/UDP 192.168.33.189:5060;received=172.25.0.1;rport=60945;branch=z9hG4bK927374352
From: <sip:31010500001320000000@3101120000>;tag=607068637
To: <sip:31010500001320000000@3101120000>
Call-ID: 998163489
CSeq: 1 REGISTER
Contact: <sip:31010500001320000000@192.168.33.189:5060>
Max-Forwards: 70
User-Agent: IP Camera
Expires: 3600
Content-Length: 0
4. 请求响应的流程
192.168.33.244:5061
响应注册请求, 直接响应给129.168.33.244:15061
opensips192.168.33.244:15061
是opensips, 把响应路由给192.168.33.189:5060
为什么opensips可以把响应发送给发起注册请求的人?
因为Via头, opensips再分发注册请求时, 添加了自己的Via信息, 处理服务响应200 OK报文时, 会把Via信息再次发给opensips, opensips一看Via是自己的信息, 直接去掉, 然后根据下一个Via信息把响应发出去
对应的报文:
# 192.168.33.244:5061响应的请求
SIP/2.0 200 OK
Via: SIP/2.0/UDP 172.25.0.2:15061;branch=z9hG4bK25ec.99ec3542.0;received=172.18.0.1
Via: SIP/2.0/UDP 192.168.33.189:5060;received=172.25.0.1;rport=60945;branch=z9hG4bK927374352
Contact: <sip:31010500001320000000@192.168.33.189:5060>;expires=3600
To: <sip:31010500001320000000@3101120000>;tag=a283172c
From: <sip:31010500001320000000@3101120000>;tag=607068637
Call-ID: 998163489
CSeq: 1 REGISTER
Expires: 3600
Date: Sun, 08 Oct 2021 15:26:52 GMT
Content-Length: 0
# opensips路由给192.168.33.189:5060的响应
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.33.189:5060;received=172.25.0.1;rport=60945;branch=z9hG4bK927374352
Contact: <sip:31010500001320000000@192.168.33.189:5060>;expires=3600
To: <sip:31010500001320000000@3101120000>;tag=a283172c
From: <sip:31010500001320000000@3101120000>;tag=607068637
Call-ID: 998163489
CSeq: 1 REGISTER
Expires: 3600
Date: Sun, 08 Oct 2021 15:26:52 GMT
Content-Length: 0