编写opensips自定义模块

2024-04-25 09:18

本文主要是介绍编写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" the
  parameters */
free_fixup_function
free_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 exported
                                  commands */
param_export_t* params;         /*!< null terminated array of the exported
                                  module parameters */
stat_export_t* stats;           /*!< null terminated array of the exported
                                  module statistics */
mi_export_t* mi_cmds;           /*!< null terminated array of the exported
                                  MI functions */
pv_export_t* items;             /*!< null terminated array of the exported
                                  module items (pseudo-variables) */
proc_export_t* procs;           /*!< null terminated array of the additional
                                  processes 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 should
                                  be "destroyed", e.g: on opensips exit */
child_init_function init_child_f;/*!< function called by all processes
                                   after 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.defs
auto_gen=
NAME=test.so
LIBS=
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自定义模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/934275

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Oracle type (自定义类型的使用)

oracle - type   type定义: oracle中自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float....但有时候我们需要特殊的格式, 如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自己定义一个数据类型 格式 :create or repla

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

HTML5自定义属性对象Dataset

原文转自HTML5自定义属性对象Dataset简介 一、html5 自定义属性介绍 之前翻译的“你必须知道的28个HTML5特征、窍门和技术”一文中对于HTML5中自定义合法属性data-已经做过些介绍,就是在HTML5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,例如我们要在一个文字按钮上存放相对应的id: <a href="javascript:" d