首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

OpenSIPS实战(八):修改sip消息-使用lumps system

目录

前言

1、lumps system简介

2、lumps system函数接口

2.1创建指定被操作lumps的函数

2.2创建用于新插入或替换lumps的函数

3、修改Contact头域与lump操作图解

3.1 使用lumps实现FixContact函数

3.2图解FixContact函数的lumps操作过程

小结

前言

SIP消息交互的过程中,经常需要对sip消息进行修改,如修改/添加SIP头域,修改SDP内容等,在使用过程中多少也会遇到需要开发来修改信令实现功能的情况。在OpenSIPS中对SIP消息执行更改的标准机制是使用所谓的块系统(lumps system)。

1、lumps system简介

OpenSIPS的lumps system效率很高,这也是opensips性能高效的一个原因之一。这些要修改的块(lumps)存储在一个列表中,并且只在OpenSIPS脚本执行完毕之后并且在SIP消息被转发之前应用到消息中(重新组包)。因此,对SIP消息所做的更改在进一步检查时不会立即反映在SIP消息中

lumps system虽然设计巧妙,但是使用起来不容易理解,我也是用过几次之后,专门翻了下代码实现来研究,才慢慢理解lumps操作的。

Lumps分为两种,SIP消息块(SIP Message Lumps)SIP响应块(SIP Reply Lumps)。这里主要介绍常会用到的SIP消息块操作。将“lumps”直接翻译为“块”对于后文的叙述而言容易造成意义不清,后面的叙述将都使用lumps来说明。

2、lumps system函数接口

SIP消息块这种类型的lumps用于操作当前SIP消息。从操作的角度来看,SIP消息块也分为两类:删除lumps(Delete Lumps)和添加lumps(Add Lumps)。但从函数接口角度来分又可以分为两类:创建指定被操作lumps的函数和创建插入或替换lumps的函数。

下面从函数接口角度对几个常用的具有代表性的lumps操作函数进行分类介绍。

2.1创建指定被操作lumps的函数

del_lump函数接口:

del_lump函数用于指定在当前sip_msg buffer中要删除的消息块的内存位置和删除长度。del_lump函数创建一个lump对象,指定删除的lump在sip_msg buffer中的位移(offset)以及删除长度(len)、lump类型LUMP_DEL(函数内部指定,不是参数type指定,下同)等,并将lump对象插入到sip_msg中的lump链表中,最后返回该lump对象的指针。

anchor_lump函数接口:

anchor_lump函数创建(malloc)一个lump对象,用于保存该lump插入点在sip_msg buffer中的位移(offset),lump操作类型设置为LUMP_NOP等,并将该lump对象插入到sip_msg中的lump链表,最后返回该lump对象的指针。

2.2创建用于新插入或替换lumps的函数

insert_new_lump_after和insert_new_lump_before接口:

insert_new_lump_after和insert_new_lump_before这两个函数分别用于创建用于新插入或替换原有内容的lumps。

insert_new_lump_after函数传入一个指定了新插入(或删除)位置的lumpafter(del_lump和anchor_lump函数返回的lump),并创建一个新的lumptmp,lump tmp用于保存新插入(或替换)内容的buffer指针以及buffer长度,lumps操作类型设置为LUMP_ADD,最后将after->after指向tmp,并返回tmp对象。

insert_new_lump_before函数操作和insert_new_lump_after函数基本相同,只是最后将传入的指定了新插入(或删除)位置的lump tmp赋值给了before->before。

这两个函数实现上和功能上区别不大,大部分场景这两个函数调用效果都是一样的,唯一的区别只是在消息重新组包的时候,insert_new_lump_before创建的lump比insert_new_lump_after创建的lump先被执行

lumps system提供的所有接口都声明在data_lump.h头文件中,这里只介绍了常用的几个。

下面举例讲解lumps操作。

3、使用lump实现FixContact函数

以下图场景为例,OpenSIPS收到的SIP消息中,Contact头域中URI地址是无效的“o8kvkeft9oak.invalid”字符串:

如果需要从OpenSIPS上修复这个问题,就需要用到lumps system。

3.1 FixContact函数实现

该函数可以实现为模块导出函数,在脚本中调用。实际上nat_traversal模块已经实现同名且功能相同的导出函数,这里做了修改,以更好的说明。

FixContact函数实现

如果在脚本逻辑对应位置中调用了该函数,则当前消息将会在转发修正这个问题,也就是contact URI中的“o8kvkeft9oak.invalid”被替换为了UAC的源地址,然后再转发给下一跳服务器。

3.2 图解FixContact函数lumps操作过程

第一步,FixContact函数从消息包中解析获得Contact头域对象,然后再解析Contact头域,获得头域中发URI对象。

第二步,计算contact URI在于消息 buffer中的偏移量,并计算要替换的字符串长度,调用del_lump函数创建指定删除字符串的lump,并保存返回的lump指针对象anchor。

第三步,使用正确的IP:Port填充addr_buf,然后调用insert_new_lump_after函数,传入anchor,addr_buf地址和addr_buf长度。

最后在消息转发前,会基于msg消息的lump链表重新进行组包,才最终将修改应用到消息中。

这里图解lumps只展示了一个概略的组包流程,实际代码实现包含很多实现细节,这里都没有展示,毕竟讲解lumps system源码实现不是本篇的目的(lumps system的源码实现还是值得学习的,如果哪天我有心情有时间也许会写一篇源码实现的介绍呢~)。

小结

OpenSIPS的lumps system从实现的很巧妙,代码应用上也经常会用到。如果需要了解更多实现细节可以去查看lumps实现源码和消息组包源码。如果需要知道其他lumps函数的使用方法也可以去查看OpenSIPS模块的源码,看是怎么使用的,毕竟这方面文档太少。

(全文完)

更多查看官方文档

http://www.opensips.org/Documentation/Development-Manual#toc11

Code Too Funny

长按订阅Code2Fun,获取更多内容

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180209G05F7J00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券