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,一经查实,立即删除!

相关文章

人民法院报:环境侵权诉讼中“虚假鉴定意见”提供者的刑事责任

2023年8月&#xff0c;最高人民法院发布了《关于审理生态环境侵权责任纠纷案件适用法律若干问题的解释》和《关于生态环境侵权民事诉讼证据的若干规定》&#xff08;以下简称《规定》&#xff09;&#xff0c;旨在进一步健全完善生态环境审判法律适用规则体系&#xff0c;推动生…

React.lazy() 懒加载

概要 React.lazy() 是 React 16.6 引入的一个功能&#xff0c;用于实现代码分割&#xff08;code splitting&#xff09;。它允许你懒加载组件&#xff0c;即在需要时才加载组件&#xff0c;而不是在应用初始加载时就加载所有组件。这种方法可以显著提高应用的性能&#xff0c…

引入 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…

Swift 扩展

Swift 扩展 Swift 是一种强大的编程语言&#xff0c;由苹果公司开发&#xff0c;用于iOS、macOS、watchOS和tvOS应用程序的开发。自2014年发布以来&#xff0c;Swift因其易于阅读和编写的语法、现代化的设计以及出色的性能而广受欢迎。本文将探讨Swift的一些关键特性&#xff…

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.为流星火雨添加按键映射 创建名为流…

Zabbix5 通过 Rsyslog 实现设备日志收集分析syslog及监控告警

一、概述 本文档详细描述了如何使用 Zabbix5 和 Rsyslog 实现对设备日志的收集、监控以及在满足特定条件下触发告警的完整流程&#xff0c;包括环境准备、Rsyslog 配置、Zabbix5 配置以及常见问题排查等内容。 二、环境准备 服务器环境 操作系统&#xff1a;CentOS&#xff08;…

开源竞争-利用kimi编程助手搭建小程序(11)

开源竞争&#xff1a; 当你无法彻底掌握技术的时候&#xff0c;你就开源这个技术&#xff0c;让更多的人了解这个技术&#xff0c;培养出更多的技术依赖&#xff0c;你会说&#xff0c;这不就是在砸罐子吗&#xff1f;一个行业里面总会有人砸罐子的&#xff0c;不是你先砸罐子&…

mybatis连接PGSQL中对于json和jsonb的处理

pgsql数据库表字段设置了jsonb格式&#xff1b;在java的实体里使用String或者对象转换会一直提示一个错误&#xff1a; Caused by: org.postgresql.util.PSQLException: ERROR: column "xx" is of type jsonb but expression is of type character varying 需要加一…

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

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

Java 处理 json 格式数据解析为 csv 格式

Java处理json格式数据解析为csv格式 如果不使用 JSON 工具库&#xff0c;你可以手动解析 JSON 格式字符串并将其转换为 CSV 格式字符串。 以下是一个简单示例&#xff0c;展示如何实现这一功能。 示例代码 下面的示例代码手动处理 JSON 字符串&#xff0c;将其转换为 CSV 格式字…

python+智谱AI-实现钉钉消息自动回复

python智谱AI-实现钉钉消息自动回复 实现了电脑窗口切换&#xff0c;截图识别未读消息&#xff0c;与语言模型交互后&#xff0c;将答案带入到钉钉窗口中。偷个懒&#xff0c;直接贴代码了&#xff0c;后续不断完善注释&#xff0c;如果遇到读不懂的地方&#xff0c;欢迎交流。…

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

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

Javascript如何获取指定网页中的内容?

这两天有一个需求&#xff0c;就是通过JS去获取网页的内容&#xff0c;当然&#xff0c;除了今天我要分享的这个方法以外&#xff0c;其实通过Ajax的Get方法也是可以实现这个功能的&#xff0c;但是Ajax就比较麻烦一些了&#xff0c;如果只是单纯的想要获取一下纯内容&#xff…

在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文…