Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dp2SSL 增加了 SIP 消息变换脚本机制 #1199

Open
DigitalPlatform opened this issue Feb 23, 2025 · 3 comments
Open

dp2SSL 增加了 SIP 消息变换脚本机制 #1199

DigitalPlatform opened this issue Feb 23, 2025 · 3 comments

Comments

@DigitalPlatform
Copy link
Owner

DigitalPlatform commented Feb 23, 2025

为增强适配第三方 SIP Server 变体消息的能力,最新版 dp2ssl 增加了用定制脚本代码(或定制的 DLL)对 SIP 消息进行变换的机制。

配置使用方法:

  1. 在 dp2ssl 的数据目录(一般在 c:\programData\dp2\dp2ssl)中创建一个名为 charging.xml 的配置文件,其内容示范如下:
<charging>
	<messageIO logging="on">
		<script lang="javascript">
message += "|||append type=" + type;
		</script>
	</messageIO>
	<settings>
		<key name="xxx" value="xxx"/>
	</settings>
</charging>

(后面专门介绍这个配置文件的结构)
(上面示范代码的作用是,在原先消息的末尾添加部分内容,其中包括请求/响应的类型)

  1. 重新启动 dp2ssl。现在从 dp2ssl 发出的 SIP 消息,会自动先经过 charging.xml 文件中的 charging/messageIO/script 元素内的脚本代码处理,然后到达目标 SIP Server;目标 SIP Server 响应的代码,会自动先经过上述脚本代码处理,然后被 dp2ssl 相关功能模块进行处理。

  2. 如果需要对上述脚本代码的执行效果进行调试观察,先要确保 charging.xml 文件中的 charging/messageIO/@logging 属性值为 'on',这样 dp2ssl 运行过程中,所有发出和收到的 SIP 消息,都会记入 dp2ssl 数据目录下 log 子目录中的当天的错误日志文件中。

@DigitalPlatform
Copy link
Owner Author

DigitalPlatform commented Feb 23, 2025

Charging.xml 配置文件结构

messageIO 元素

位于根元素之下级。
定义了 SIP 消息进出过程中的一些特性参数。

logging 属性定义了是否将 SIP 消息记入错误日志中。为 "on" 表示要记载;其它值(或者 logging 属性缺省)表示不记载。

script 元素

位于 messageIO 元素之下级。
定义了 SIP 消息进出过程中,对消息进行变换的脚本程序代码。

script/@lang 属性

lang 属性定义了语言类型,目前支持 "javascript" 和 "ZHAO" 两种语言。

元素内的文本部分是程序代码。如果直接在 script 元素的文本部分内书写代码,需要注意 ‘<’ ‘>’ 等字符需要表达为 XML 的 entity 形态,例如:

<script lang="javascript">
    ......
    if (i &gt; 1) ...
    ......
</script>

而这样用 CDATA 方式书写则比较容易阅读:

<script lang="javascript">
    <![CDATA[
    ......
    if (i > 1) ...
    ......
    ]]>
</script>

这两种书写方式效果是等同的。

ZHAO 语言的 script 元素举例:

<script lang="ZHAO">
  msg:93:beg:2
    fld:CO:ign
</script>

(ZHAO 语言的原理和编制方法请参考相关文档)

script/@fileName 属性

fileName 属性定义了 DLL 动态链接库的文件名。这样 SIP 消息转换就由触发 DLL 中的特定函数完成。

例如:

<script fileName="c:\programData\dp2\dp2ssl\SipFilter\dp2SSL.SampleSipMessageFilter.dll">
</script>

这种用于 SIP 消息过滤的 DLL 要求是从 DigitalPlatform.Interfaces.ISipMessageFilter 接口派生。可以参考 dp2 repo 中的 DigitalPlatform.Interfaces Project 内的代码。

dp2 repo 中也提供了一个示范的 SIP 消息过滤 DLL Project 的源代码,可以参考 dp2 repo 中的 dp2SSL.SampleSipMessageFilter Project。

多个 script 元素

messageIO 元素下可以定义多个 script 元素。宿主程序会按照它们定义的顺序,顺次触发它们,前一个 script 元素变换后的 message 会作为后一个 script 元素的输入,像连接在一起的管道一样发生作用,对 message 进行多次变换。

@DigitalPlatform
Copy link
Owner Author

DigitalPlatform commented Feb 23, 2025

javascript 脚本代码的作用原理

环境变量

在脚本被触发以前,javascript 解释器环境会预先准备好以下几个变量,便于脚本实现具体业务功能。

context

这是一个 ScriptContext 类型的对象(可参考 dp2ssl 源代码),生存周期是和 SIP 通讯通道的生命周期一致。也就是说,每一次 javascript 脚本代码被触发调用之间,可以用它来存储和传递各种信息,让状态持久。

用法举例:

......
var count = context.Get("count");
......
context.Set("count", count +1);
......

另外 context 的内容集合中如果包含 key 名字为 "verifyMessage" 的事项,则可以控制宿主 dp2ssl 后续环节在解析 SIP 消息的阶段,如何进行消息正确性校验。这个事项的值可以为 "",或者 "fix,var,requir" 或者这三个值的任意组合。"" 表示全功能校验,也就是 "fix,var,requir";fix 表示要校验固定长字段的正确性; var 表示要校验变长字段的正确性,requir 表示要校验必备字段是否具备。

如果上述 "verifyMessage" 事项的值为 ''[none]',则表示不进行正确性校验。

最后,如果 context 的内容集合中不包含 key 名字为 "verifyMessage" 的事项,则宿主 dp2ssl 后续环节的对 SIP 消息的校验,会按照 charging.xml 中 /settings/key[@name='SIP消息校验']/@value 这个属性值的定义来进行。(也就是说根目录下的 settings 元素下的 key 元素,满足 name 属性等于 "SIP消息校验" 的 key 元素的 value 属性的值)

(注: 如果 charging.xml 中 /settings/key[@name='SIP消息校验']/@value 这个属性缺省,则相当于全功能校验 )

message

[in,out]
这是一个 string 类型的对象,是本次即将发送给远端 SIP Server 的消息正文(type 为 'request' 时),或者从远端 SIP Server 收到的消息正文(type 为 'response' 时)。

javascript 脚本代码可以对它的内容进行修改,当脚本返回以后,宿主程序会用修改后的内容继续后继处理。

SIP 消息的具体格式请参考相关文档。

error

[out]
这是一个 string 类型的对象,javascript 脚本代码可以对它赋值,当脚本换回以后,宿主程序会判断它的值,如果为 null 或者 "",则表示脚本代码没有报错;否则就是报错信息内容。

期待的功能

需要用 C# 实现一个方便 javascript 操作的 SIP 消息解析、处理的类,这样可以避免直接用 javasript 脚本代码做繁琐的字符串编程。这部分计划研究以后逐步加入。

@DigitalPlatform
Copy link
Owner Author

DigitalPlatform commented Feb 25, 2025

SIP 消息变换语言 ZHAO 的基本概念和用法

quirk:GBK					# 消息怪癖处理规则
  msg:18:beg:32		# 消息ID 18
    fld:CF:ign			# 字段 AS 忽略
    fld:AS:tsf:AT 		# 字段 AS 转换 AT
    fld:BH:tsf:AT:map	# 字段 BH 转换 AT 映射表
      map:b:03			# 值 b 转换成 03
  msg:19:ign			# 消息 19 忽略
  msg:93:beg:4			# 消息ID 93
    fld:CP:ign			# 字段 CP 忽略
    fld:LX:add:CN-0000001-DG    # 字段 LX 新增,预设值 CN-0000001-DG
    fld:LN:add:              # 字段 LN 新增,脚本使用返回值
function returnCode(){
    return "CN-0000001-DG"
}

    fld:CN:tsf:AT 		# 字段 CN 转换 AT
    fld:CO:tsf:AN		# 字段 CO 转换 AN 映射表
    fld:CQ:tsf:AQ:map	# 字段 BH 转换 AT 映射表
      map:b:03			# 值 b 转换成 03
  msg:19:ign			# 消息 19 忽略

可以按照这个规则定义方式对所有消息进行过滤筛选,对不符合要求的参数进行二次加工

quirk:英文怪癖,泛指sip2的一些奇怪写法,参数1:字符集,终端跟服务器进行交互时使用的字符集,可以规避因为设备端编码与服务器不一致导致的乱码

msg:消息缩写,参数1:消息ID,sip2消息的前两个字节,消息处理的依据,参数2:beg,begin的缩写,如果|之前的第一个字段需要处理,为了快速定位,需要指定固定长度的头的长度,参数3:头长,包含协议头2个字节在内

fld:字段field缩写,目前有4中处理方式,1是过滤掉,关键字是ign,ignore忽略的缩写;2是变换,将字段重定义为另一个字段,关键字是tsf,transfer缩写;3是对值进行更改,比如一些状态需要修复,关键字是map,标识接下来需要枚举出映射关系;4是add,添加,支持预设值添加与脚本返回值添加

map:mapper的缩写,两个参数,第一个参数是消息里的原始值,第二个参数是准备替换成的值,同一个字段的枚举值可能有多个,需要写多条map来匹配。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant