OpenSIPS 转发 JSSIP 注册消息到 FreeSWITCH

OpenSIPS IP 地址:192.168.31.213

FreeSWITCH IP 地址: 192.168.31.166

转发注册消息的路由代码应该是:

if (is_method("REGISTER")) {save("location", "r");if ($pr == "ws" || $pr == "wss") {$var(new)= $ct;xlog("L_INFO", "[$cfg_line]|$ci|new contact=$var(new)\n");# 删除 ";transport=ws" (如果有)$var(new) = $(var(new){re.subst,/^(.*)(;transport=ws)(.*)/\1\3/});# 删除 ";transport=wss" (如果有)$var(new) = $(var(new){re.subst,/^(.*)(;transport=wss)(.*)/\1\3/});xlog("L_INFO", "[$cfg_line]|$ci|transformed contact $var(new)\n");remove_hf("Contact");append_hf("Contact: $var(new)\r\n");}$du = "sip:192.168.31.166";append_hf("Path: <sip:$tU@192.168.31.213:5060;r2=on;lr;pr=$pr>\r\n");t_relay();exit;
}

 有几个细节需要留意下:

1. save() 函数的 第二个参数是 "r", 就是 no reply 的意思,查下文档就知道了。no reply 的意思其实就是 REGISTER 不是我处理,但从我这经过,我偷偷存一份。

2. 如果是 JSSIP 注册,那么修改 Contact 头,删除 ";transport=ws" 或者删除 ";transport=wss" (转换函数支持正则表达式,想清楚了之后发现并不复杂)。

3. 增加 Path 头,这样 FreeSWITCH 回叫该注册用户的时候会把 INVITE 消息发到 OpenSIPS


上面仅仅讲了个大概,还有很多细节需要进一步说明

1. 不调用 save 行不行?当然可以,但 Path 头要增加一个参数,要把 JSSIP 的 地址记录下来。Kamailio 管这个叫 $sut(可以增加这个参数";sut=$sut"),其实就是 $si + $sp + $pr 的组合,但 我查了下 OpenSIPS 的文档,好像并没有对应的伪变量(换言之,只能自己组合)。

2. 为什么要修改 JSSIP 注册请求的 Contact 头,回答是跟 FreeSWITCH 的处理有关,如果发现Contact 里面的 transport=ws 或者是 wss, 那么会自动激活 media_webrtc(FS 通道变量)。

3. Path 是 一个 SIP 规范,FreeSWITCH 支持该规范, FreeSWITCH 回叫该注册用户时,INVITE 发到 OpenSIPS, Route 头等于 Path 头。换言之,Path 增加了任何参数, INVITE 的 Route 都会完整地还回来。


JSSIP 成功注册后, 在 FS1.10.7 一侧输入 fs_cli -x 'show registrations as xml',得到的是:

<result row_count="1">
  <row row_id="1">
    <reg_user>1002</reg_user>
    <realm>192.168.31.166</realm>
    <token>uq472289ha85maa9g4m304</token>
    <url>sofia/internal/sip:c5pjist8@0flvmn2gtt72.invalid;fs_path=sip%3A1002%40192.168.31.213%3A5060%3Br2%3Don%3Blr%3Bpr%3Dws</url>
    <expires>1731241805</expires>
    <network_ip>192.168.31.213</network_ip>
    <network_port>5060</network_port>
    <network_proto>udp</network_proto>
    <hostname>DESKTOP-QEPDSM1</hostname>
    <metadata></metadata>
  </row>
</result>

我们重点看 url 的内容,解码后的内容为:

sofia/internal/sip:c5pjist8@0flvmn2gtt72.invalid;fs_path=sip:1002@192.168.31.213:5060;r2=on;lr;pr=ws

FS 回叫时是这样的:

INVITE sip:c5pjist8@0flvmn2gtt72.invalid SIP/2.0
Via: SIP/2.0/UDP 120.229.53.249;rport;branch=z9hG4bK5vgj6Q04S7gHQ
Route: <sip:1002@192.168.31.213:5060>;r2=on;lr;pr=ws
Max-Forwards: 70
From: <sip:0000000000@192.168.31.166>;tag=pr7cU4X9cHm5j
To: <sip:c5pjist8@0flvmn2gtt72.invalid>
Call-ID: d5a5bb3d-1a01-123e-b7a9-c1d2a5f21113
CSeq: 91066998 INVITE
Contact: <sip:mod_sofia@120.229.53.249:5060>
User-Agent: FreeSWITCH-mod_sofia/1.10.7-release~883d2cb662~64bit

...

我们重点看 Route 头,其实是有问题的

我们换成 FreeSWITCH 1.10.12 (1.10.8开始修复了该问题),再来测试一遍


<result row_count="1">
  <row row_id="1">
    <reg_user>1002</reg_user>
    <realm>192.168.31.166</realm>
    <token>0d4jd4fp5o4kksjdj8rr22</token>
    <url>sofia/internal/sip:fl4lcbh8@hta3sufe4u62.invalid;fs_path=%3Csip%3A1002%40192.168.31.213%3A5060%3Br2%3Don%3Blr%3Bpr%3Dws%3E</url>
    <expires>1731242441</expires>
    <network_ip>192.168.31.213</network_ip>
    <network_port>5060</network_port>
    <network_proto>udp</network_proto>
    <hostname>DESKTOP-QEPDSM1</hostname>
    <metadata></metadata>
  </row>
</result>

url 为 sofia/internal/sip:fl4lcbh8@hta3sufe4u62.invalid;fs_path=<sip:1002@192.168.31.213:5060;r2=on;lr;pr=ws>

INVITE 消息为:

INVITE sip:fl4lcbh8@hta3sufe4u62.invalid SIP/2.0
Via: SIP/2.0/UDP 120.229.53.249;rport;branch=z9hG4bKS702tQDXH37HS
Route: <sip:1002@192.168.31.213:5060;r2=on;lr;pr=ws>
Max-Forwards: 70
From: <sip:0000000000@192.168.31.166>;tag=veecU60t7QDUK
To: <sip:fl4lcbh8@hta3sufe4u62.invalid>
Call-ID: a4ccc9d4-1a02-123e-67a0-1b1b392ee782
CSeq: 91067172 INVITE

...

现在再看 Route 头,就是对的了(之前尖括号的位置不对)


OpenSIPS 测试的版本是 2.4.11,但是本文给的路由代码应该是所有 OpenSIPS 版本都通用的。

建议您仔细读下本文,至少我没找到很多质量还不错的 OpenSIPS 中文资料。

怎样处理 FS INVITE 呢?这个留着以后讲。


FS INVITE 路由应该怎么写呢?

首先,我们修改写上面的 REGISTER 路由,把 username 放 Contact 里面,这并不难

其次,针对 FS 的不同版本,路由代码要做适配

$var(route)  = $hdr(Route);

xlog("route = $var(route)\n");

一种是这样: <sip:1002@192.168.31.213:5060;r2=on;lr;pr=ws>

还有一种是这样: <sip:1002@192.168.31.213:5060>;r2=on;lr;pr=ws

路由代码如下:

if (!is_method("INVITE") return;

$var(route) = $hdr(Route);

if ($var(route) == NULL) return;

xlog("+++route = $var(route)\n");

# 删除开始的 "<"
$var(route) = $(var(route){re.subst,/^<(.*)/\1/});
# 删除 ">",不管它在中间还是在末尾
$var(route) = $(var(route){re.subst,/^(.*)>(.*)/\1\2/});
# 取 user
$var(user) = $(var(route){uri.user});
# 取 协议
$var(proto) = $(var(route){uri.params}{param.value,pr});

$var(aor) = "sip:" + $var(user)  + "@" + $rd;
if (!lookup("location", "m", "$var(aor)")) {
    t_reply("404", "not found");
    exit();
}

if ($var(proto) == "ws" || $var(proto) == "wss"){
    setbflag(DST_WS);
}
route(relay);
exit

如果 route 头有别的参数,照这个例子解析,并不难。如果有 sut 参数,更方便。

# $var(sut) = ...

$du = $var(sut);

route(relay);

exit; 

if ($var(proto) == "ws" || $var(proto) == "wss"){
    setbflag(DST_WS);
}

这一段貌似也可以注释掉, 处理注册时 只要设置了 bflag, lookup 时 会自动还回来

OpenSIPS 是个好软件,但入门有门槛

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/60254.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

引入 axios,根据 api 文档生成调用接口

起步 | Axios Docs 安装 axios npm install axios 生成 api 调用接口【可选】 https://github.com/ferdikoomen/openapi-typescript-codegen 安装 npm install openapi-typescript-codegen --save-dev 然后执行生成代码 # http://localhost:8805/api/user/v3/api-docs&a…

2款使用.NET开发的数据库系统

今天大姚给大家分享2款使用.NET开发且开源的数据库系统。 Garnet Garnet是一款由微软研究院基于.NET开源的高性能、跨平台的分布式缓存存储数据库&#xff0c;该项目提供强大的性能&#xff08;吞吐量和延迟&#xff09;、可扩展性、存储、恢复、集群分片、密钥迁移和复制功能…

ARM-8 定位发布版本 pstree 程序的 main 地址

逆向时如何找到main&#xff0c;如下&#xff1a; 1.readelf -h pstree ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2s complement, little endian Versi…

13.UE5流星火雨,引导施法技能制作

2-15 流星火雨&#xff0c;引导施法技能制作、随机数_哔哩哔哩_bilibili 目录 1.为流星火雨添加按键映射 2.创建流星火雨的动画蒙太奇 3.实现播放动画蒙太奇的逻辑 ​编辑 4.定义发射一波流星火雨的发射物 5.使用动画通知释放流星火雨 1.为流星火雨添加按键映射 创建名为流…

Web大型网站的性能测试要求和工具方法

Web大型网站的性能测试要求和工具方法涉及多个层面的考量&#xff0c;旨在确保网站在高并发访问、大数据量处理、复杂交互场景下仍能保持良好的用户体验和系统稳定性。以下是针对大型网站性能测试的主要要求和相应的工具与方法&#xff1a; 性能测试要求 1. 高并发处理能力&…

贪心算法day3(最长递增序列问题)

目录 1.最长递增三元子序列 2.最长连续递增序列 1.最长递增三元子序列 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;我们只需要设置两个数进行比较就好。设a为nums[0]&#xff0c;b 为一个无穷大的数&#xff0c;只要有比a小的数字就赋值…

在CentOS7传统部署wordpress

1 环境准备 所需环境说明CentOS7.9ip地址&#xff1a;10.0.0.7&#xff0c;可以上网PHP72系列软件下面会介绍MySQL数据库暴露端口3306&#xff0c;用户wordpress&#xff0c;库wordpressnginx版本任意wordpres v6.5.2代码下载地址&#xff1a;https://cn.wordpress.org/wordpr…

文献阅读 | Nature Methods:使用 STAMP 对空间转录组进行可解释的空间感知降维

文献介绍 文献题目&#xff1a; 使用 STAMP 对空间转录组进行可解释的空间感知降维 研究团队&#xff1a; 陈金妙&#xff08;新加坡科学技术研究局&#xff09; 发表时间&#xff1a; 2024-10-15 发表期刊&#xff1a; Nature Methods 影响因子&#xff1a; 36.1&#xff0…

vs2022搭建opencv开发环境

1 下载OpenCV库 https://opencv.org/ 下载对应版本然后进行安装 将bin目录添加到系统环境变量opencv\build\x64\vc16\bin 复制该路径 打开高级设置添加环境变量 vs2022新建一个空项目 修改属性添加头文件路径和库路径 修改链接器&#xff0c;将OpenCV中lib库里的o…

GA/T1400视图库平台EasyCVR多品牌摄像机视频平台前端监控摄像头镜头的基础知识

在现代安全监控系统中&#xff0c;摄像机镜头作为捕捉图像的关键组件&#xff0c;其选择和应用直接影响到监控图像的质量和系统的整体性能。随着技术的发展&#xff0c;摄像机镜头的种类和功能也在不断扩展&#xff0c;以适应各种复杂的监控环境和需求。对于相机成像来讲&#…

省级数字经济发展水平数据(2011-2022年)

数字经济是指以数据资源为关键要素&#xff0c;以现代信息网络为主要载体&#xff0c;以信息通信技术融合应用、全要素数字化转型为重要推动力&#xff0c;促进公平与效率更加统一的新经济形态。 2011-2022年省级数字经济发展水平数据&#xff08;&#xff09;.zip资源-CSDN文…

【WRF模拟】全过程总结:WPS预处理及WRF运行

【WRF模拟】全过程总结:WPS预处理及WRF运行 1 数据准备1.1 嵌套域设置(Customize domain)-基于QGis中gis4wrf插件1.2 静态地理数据1.2.1 叶面积指数LAI和植被覆盖度Fpar(月尺度)1.2.2 地面反照率(月尺度)1.2.3 土地利用类型+不透水面积1.2.4 数据处理:geotiff→tiff(W…

银行家算法(模拟)

银行家算法是一种避免死锁的有效算法&#xff0c;它借鉴了银行家贷款的策略。在分配资源之前&#xff0c;银行家会检查系统是否有足够的资源满足进程的最大需求&#xff0c;若有&#xff0c;则暂时分配资源&#xff0c;然后继续检查剩余资源是否足够满足其他进程的最大需求。只…

「QT」几何数据类 之 QSizeF 浮点型尺寸类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

【动手学电机驱动】STM32-FOC(3)STM32 三路互补 PWM 输出

STM32-FOC&#xff08;1&#xff09;STM32 电机控制的软件开发环境 STM32-FOC&#xff08;2&#xff09;STM32 导入和创建项目 STM32-FOC&#xff08;3&#xff09;STM32 三路互补 PWM 输出 STM32-FOC&#xff08;4&#xff09;IHM03 电机控制套件介绍 STM32-FOC&#xff08;5&…

Spark中的shuffle

Shuffle的本质基于磁盘划分来解决分布式大数据量的全局分组、全局排序、重新分区【增大】的问题。 1、Spark的Shuffle设计 Spark Shuffle过程也叫作宽依赖过程&#xff0c;Spark不完全依赖于内存计算&#xff0c;面临以上问题时&#xff0c;也需要Shuffle过程。 2、Spark中哪…

ffmpeg 视频滤镜:屏蔽边框杂色- fillborders

滤镜描述 fillborders 官网链接 > FFmpeg Filters Documentation fillborders滤镜有几种方式帮你屏蔽边框的杂色、不好的图案。 滤镜使用 参数 left <int> ..FV.....T. set the left fill border (from 0 to INT_MAX) (default 0)right …

「C/C++」C++标准库 之 #include<iostream> 标准输入输出

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

智能合约在供应链金融中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 智能合约在供应链金融中的应用 智能合约在供应链金融中的应用 智能合约在供应链金融中的应用 引言 智能合约概述 定义与原理 发展…

设计模式之责任链模式(Chain Of Responsibility)

一、责任链模式介绍 1、责任链模式介绍 职责链模式(chain of responsibility pattern) 定义: 避免将一个请求的发送者与接收者耦合在 一起&#xff0c;让多个对象都有机会处理请求。将接收请求的对象连接成一条链&#xff0c;并且沿着这条链 传递请求&#xff0c;直到有一个对…