Kamailio学习【二】--自定义模块


写在前面的话:里面的截图除非特殊说明,都是来自sr_module.h

参考:https://blog.csdn.net/ttomqq/article/details/38821411

一、关于版本

定义每一个模块都要说明这个模块的结构,以便于让kamailio能解释它,包括模块导出函数的结构cmd_export_和模块整体的结构module_exports。在sr_module.h中有两种版本的模块结构,一个是SER,一个是kam,是这样定义的:

 

 

这里的cmd_export_t和module_exports即可代表ser的也可以代表kam的。在自己定义模块时候直接由结构的内容体现是哪种版本(个数)。

 

模块导出函数结构:

 

 

模块结构:

 


有默认使用哪种版本的定义,猜想应该是从这里默认定义的:

 

默认版本是SER的,但是没找到用另一个版本kam所代表的数值,在json_mod.c中就是用的kam版本的(下图)


但是里面的版本声明 MODULE_VERSION仍然是SER的意思,这里面应该有一些定义是没注意到的,也就是什么时候可以用kam版本,这个我没找到,希望有大神能帮我解惑

二、结构具体含义

1对于模块导出函数结构:

 

第一个参数是该module导出到opensips脚本中的函数名

第二个参数是对应的具体执行函数。cmd_function的函数定义为

 

从第二个参数起都是字符串。具体使用多少个参数由结构体第三个参数决定

对于cmd_function,返回值小于0表示函数执行出错,返回值等于0会使该次脚本执行结束;返回值大于0表示函数执行正常

第四个参数fixup function,主要用于将脚本传入的参数转换成int、正则表达式等其他种类的参数。常用的类型转换定义在mod_fix.h中,一般直接调用

第五个参数用于描述该导出函数可以在哪段路由中被执行。可选的值定义在route.h中:

 

kam版本比ser的多了一个free_fixup_function参数,用于释放fixup function执行时申请的内存

 

2、对于模块结构:

 

char* name: 模块的名字

ser_cmd_export_t* cmds:前面定义的模块导出函数,这里如果一个模块里多于两个导出函数的情况下就要定义ser_cmd_export_t类型的结构体数组cmds[],每一个元素都是一个ser_cmd_export_t类型的结构体,各对应一个导出函数。

rpc_export_t* rpc_methods:远程程序调用的导出函数(rpc.h中定义的)。

 

param_export_t* params:参数导出,很多参数的时候也是定义一个param_export_t类型的数组,每个数组元素都是对这个参数的说明,例如acc_mod.c中的184行(部分):

 

init_function init_f: 模块初始化化函数,只在启动的时候被执行一次

response_function response_f: 用于回复,有yesnonull也行,不知道做什么的。

destroy_function destroy_f: 模块销毁时被调用

onbreak_function onbreak_f;:不知道做什么的,onbreak_function120行:

typedef void (*onbreak_function)(struct sip_msg*);是指向sip_msg结构体的一个指针。

child_init_function init_child_f: 模块在每个子进程中的初始化函数。因kamailio的架构是多进程的,像数据库连接这些必须在每个子进程内自己创建一份

 

unsigned int dlflags: 一般都把值设为DEFAULT_DLFLAG,后面的stat_nn_pv_还没看是做什么的。

proc_export_t* procs: 定义模块自己的独立运行进程

三、编写一个简单的模块

1、写模块主体代码test.c文件

在目录/usr/local/src/kamailio-5.1/kamailio/src/modules(也就是下载kamailio源码的位置那)建立一个名为test的文件夹,编写模块主体代码test.c文件。

cd /usr/local/src/kamailio-5.1/kamailio/src/modules

sudo mkdir test

cd test

sudo vi test.c   /*根据自己常用的编辑器来即可*/

test.c文件如下:

/*

*时间:2018年3月29日16点24分

*作者:cxy

*模块名:test

*导出函数名:my_test

*功能:在初始化的时候在日志输出“cxy-initializing...”,在每一个request(invite,subscribe,

*register,cancel等等)到来时候输出“Receive message 123456”,为了看是否模块添加成功

*输入:123456(或者其他)

*输出:Receive message 123456(或者其他)

*/

#include "../../core/sr_module.h"

MODULE_VERSION
 
static int mod_init(void);

static int my_test(struct sip_msg* _msg, char *param);

/* Exported functions */

static cmd_export_t cmds[]={

{"my_test", (cmd_function)my_test, 1, 0, ANY_ROUTE},       /*在任何路由块都能用*/

{0, 0, 0, 0, 0}

};

/* Module interface */

struct ser_module_exports exports = {

"test",	       /**< null terminated module name */

 cmds,         /**< null terminated array of the exported

                                              commands */

 0,              /**< null terminated array of exported rpc methods */

 0,              /**< null terminated array of the exported  module parameters */
 
 mod_init,      /**< Initialization function */

 0,              /**< function used for responses, returns yes or no; can be null */

 0,              /**< function called when the module should be "destroyed", e.g: on ser exit;

                                                                	can be null */
 
 0,

 0,              /**< function called by all processes after the fork */

};

static int my_test(struct sip_msg* _msg, char *param)

{

   LM_INFO("Receive message %s\n", param);

   return 1;

}

static int mod_init(void)

{

LM_INFO("cxy-initializing...\n");

return 0;

}

2、编写Makefile文件

如果这个module不需要连接其他额外的库,只要把NAME后面生成库的名字改成test.so。如下所示:

#

#test makefile

#

#WARNING: do not run this directly. it should be run by the master Makefile

include ../../Makefile.defs

auto_gen=

NAME=test.so

LIBS=

DEFS+=-DSER_MOD_INTERFACE

include ../../Makefile.modules

3、编译

编译这个模块,除非在src目录下的主Makefileexclude_modules中加入了这个模块的名字,就不编译这个模块。

cd /usr/local/src/kamailio-5.1/kamailio

sudo make all

sudo make install

(按理说不用再次安装吧?但是如果不再安装的话我发现生成的库文件test.so不能被导入/usr/local/lib64/kamailio/modules中,还是说是应该要安装一遍的?)

  由于一开始我是仿照https://blog.csdn.net/ttomqq/article/details/38821411里面的test模块,修改了一些版本的差异,一开始我是按照kamailio版本写的模块但总是提示警告,提示我有多余的元素。经过比较,不管是cmd模块导出函数声明还是module模块导出声明,SER版本的的确是比kam版本的元素个数要少(SER版本cmd5个元素,module9个;kam版本cmd6个,module12个)。默认版本是SER,因此下面的警告根源在版本这里,改成了SER版本就行了。

 

4、载入新模块

不载入的话kamailio不会自己添加这个功能的,在kamailio.cfg文件中相应位置加入以下语句:

loadmodule "test.so"

把新编写的模块加入路由之中,在路由逻辑的request逻辑下插入:

my_test("123456");

5、验证模块是否添加成功

打开kamailio,注册用户并登陆,见https://blog.csdn.net/qq_36069590/article/details/79106771,可以看到路由被执行到时,日志有输出:

 

 

PS:这里有什么说错的麻烦能告诉我一下,谢谢!作为一个kamailio初学者,我感觉要学的东西太多了,这可能是和我专业不是计算机相关的有关吧。知识是一点点积累的,需要什么就去学什么就好了,涉及到基础的东西就去系统的看看教材或视频。今天花了一下午把昨天学到的东西记录在这里,在这里就顺便给自己打打气,加油cxy。

           任重而道远,与君共勉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章