本文主要是介绍编写opensips自定义模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
编写module需要用到的各种数据结构定义在sr_module.h。其中比较重要的是cmd_export_t,用于声明这 个module的导出函数
struct cmd_export_ {char* name; /* null terminated command name */cmd_function function; /* pointer to the corresponding function */int param_no; /* number of parameters used by the function */fixup_function fixup; /* pointer to the function called to "fix" theparameters */free_fixup_functionfree_fixup; /* pointer to the function called to free the"fixed" parameters */int flags; /* Function flags */};
第一个参数是该module导出到opensips脚本中的函数名
第二个参数是对应的具体执行函数。cmd_function的函数定义为
typedef int (*cmd_function)(struct sip_msg*, char*, char*, char*, char*, char*, char*);
从第二个参数起都是字符串。具体使用多少个参数由结构体第三个参数决定
对于cmd_function,返回值小于0表示函数执行出错,返回值等于0会使该次脚本执行结束;返回值大于0 表示函数执行正常
第四个参数fixup function,主要用于将脚本传入的参数转换成int、正则表达式等其他种类的参数。 opensips已经定义好了常用的类型转换,定义在mod_fix.h中,一般直接调用现成的即可以
第五个参数free_fixup_function,用于释放fixup function执行时申请的内存
第六个参数,用于描述该导出函数可以在哪段路由中被执行。可选的值包括
REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE等
另外一个比较重要的结构体是
struct module_exports{char* name; /*!< null terminated module name */char *version; /*!< module version */char *compile_flags; /*!< compile flags used on the module */unsigned int dlflags; /*!< flags for dlopen */cmd_export_t* cmds; /*!< null terminated array of the exportedcommands */param_export_t* params; /*!< null terminated array of the exportedmodule parameters */stat_export_t* stats; /*!< null terminated array of the exportedmodule statistics */mi_export_t* mi_cmds; /*!< null terminated array of the exportedMI functions */pv_export_t* items; /*!< null terminated array of the exportedmodule items (pseudo-variables) */proc_export_t* procs; /*!< null terminated array of the additionalprocesses reqired by the module */init_function init_f; /*!< Initialization function */response_function response_f; /*!< function used for responses,returns yes or no; can be null */destroy_function destroy_f; /*!< function called when the module shouldbe "destroyed", e.g: on opensips exit */child_init_function init_child_f;/*!< function called by all processesafter the fork */};
char* name: 模块的名字
char *version: 一般都把值设为MODULE_VERSION
char *compile_flags: 一般都把值设为DEFAULT_DLFLAGS
接着几个参数设置模块的导出函数、导出参数、MI命令等
proc_export_t* procs: 定义模块自己的独立运行进程
init_function init_f: 模块初始化化函数,只在opensips启动的时候被执行一次
response_function response_f: 很少有模块需要用到,尚不清楚有什么用
destroy_function destroy_f: 模块销毁时被调用
child_init_function init_child_f: 模块在每个子进程中的初始化函数。因为opensips的架构是多进 程的,像数据库连接这些必须在每个子进程内自己创建一份
对编写module有个基本的认识以后,可以开始着手写一个简单的module
1、在opensips/modules目录下新建一个目录test
2、编写这个test module的Makefile。如果这个module不需要连接其他额外的库,Makefile是相当的简 单,只要把NAME后面生成库的名字改一下
include ../../Makefile.defsauto_gen=NAME=test.soLIBS=include ../../Makefile.modules
3、编写这个模块的主体代码test.c
#include "../../sr_module.h"static int mod_init(void);/* Exported functions */static int my_test(struct sip_msg* _msg, char *param);static cmd_export_t cmds[] = {{ "my_test", (cmd_function)my_test, 1, 0, 0,REQUEST_ROUTE},{0, 0, 0, 0, 0, 0}};/* Module interface */struct module_exports exports= {"test", /* module name*/MODULE_VERSION,DEFAULT_DLFLAGS, /* dlopen flags */cmds, /* exported functions */0, /* module parameters */0, /* exported statistics */0, /* exported MI functions */0, /* exported pseudo-variables */0, /* extra processes */mod_init, /* module initialization function */0, /* response function */0, /* destroy function */0, /* per-child init function */};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("initializing...\n");return 0;}
4、建立好这个模块的目录之后,opensips就会去编译这个模块,除非你在Makefile.conf的 exclude_modules中加入了这个模块的名字。按照正常opensips的编译步骤进行编译
5、把新编写的模块加入路由之中
loadmodule "msg_trace.so"
在路由的某个地方插入
my_test("1234");
可以看到路由被执行到时,日志有输出
Aug 2 06:20:45 simope-0A ./opensips[2346]: INFO:test:my_test: Receive message 1234
主要参考textops、cachedb_local、cfgutils等较为简单的module
另外也可以参考同源的kamailio项目,虽然结构上也有细微的变换,但是kamailio的开发文档相对比较 齐全
http://www.asipto.com/pub/kamailio-devel-guide/#c16moduledev
这篇关于编写opensips自定义模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!