searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

如何在kamailio编写一个自定义的模块作为http服务

2024-08-07 09:33:48
28
0

1、主要结构说明

1.1、导出参数

模块对外提供的指定相关参数入口,主要kamailio脚本加载模块时指定初始化参数

对应结构如下:

typedef struct param_export {
	char* name;             /**< null terminated param. name */
	modparam_t type;        /**< param. type */
	void* param_pointer;    /**< pointer to the param. memory location */
} param_export_t;

参数说明:

name:导出到脚本中对应的参数名称

type:参数类型

param_pointer:程序内存储对应参数的指针

1.2、导出方法

模块对外提供的函数调用入口,主要是kamailio脚本处理对应业务时调用对应模块函数实现具体业务逻辑。

对应结构如下:

typedef 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; /**< function called to free the "fixed"
									   parameters */
	unsigned int flags;     /**< Function flags */
} cmd_export_t;

参数说明:

name:导出到脚本中对应的方法名

function:模块内对应的处理函数,一般函数返回值等于0表示成功,小于0表示失败

param_no:方法对应的参数个数

fixup:解析参数的方法

free_fixup:释放参数资源的方法

flag:描述导出方法可以在脚本内的哪段路由中被执行

flag可选值:

#define REQUEST_ROUTE (1 << 0)
#define FAILURE_ROUTE (1 << 1)
#define TM_ONREPLY_ROUTE (1 << 2)
#define BRANCH_ROUTE  (1 << 3)
#define ONSEND_ROUTE  (1 << 4)
#define ERROR_ROUTE   (1 << 5)
#define LOCAL_ROUTE   (1 << 6)
#define CORE_ONREPLY_ROUTE (1 << 7)
#define BRANCH_FAILURE_ROUTE (1 << 8)
#define ONREPLY_ROUTE (TM_ONREPLY_ROUTE|CORE_ONREPLY_ROUTE)
#define ONEVENT_ROUTE (1 << 9)
#define EVENT_ROUTE   (REQUEST_ROUTE|ONEVENT_ROUTE)
#define ANY_ROUTE     (0xFFFFFFFF)

1.3、导出模块

对应脚本内调用的模块信息

对应结构如下:

typedef struct module_exports {
	/**< null terminated module name */
	char* name;
	/**< flags for dlopen  */
	unsigned int dlflags;
	/**< null terminated array of the exported commands (config functions)*/
	cmd_export_t* cmds;
	/**< null terminated array of the exported module parameters */
	param_export_t* params;
	/**< null terminated array of exported rpc methods */
	rpc_export_t* rpc_methods;
	/*!< null terminated array of the exported module items (pseudo-variables) */
	pv_export_t* pv_items;
	/**< function used for responses, returns yes or no; can be null */
	response_function response_f;
	/**< Initialization function */
	init_function init_mod_f;
	/**< function called by all processes after the fork */
	child_init_function init_child_f;
	/**< function called when the module is "destroyed" (on server shut down) */
	destroy_function destroy_mod_f;
} module_exports_t;

主要参数说明:

name:模块名

cmds:导出的方法

params:导出的参数

init_mod_f:初始化函数

init_child_f:模块在每个子进程中的初始化函数

destroy_mod_f:模块销毁时的处理函数

2、http服务模块编写

2.1、编写模块基本结构

static str test_mod_uri = str_init("/self/test_mod");

static int w_test_dispatch(sip_msg_t* msg);
static int w_test_check_uri(sip_msg_t* msg);
static int mod_init(void);
static void mod_destroy(void);

//需要用http_api接口对收到的请求做响应操作
xhttp_api_t         xhttp_api; 

int int_param           = 0; 
str str_param     = STR_NULL;


void* testInit = NULL;

/* module commands */
static cmd_export_t cmds[] = {
	{"test_dispatch", (cmd_function)w_test_dispatch, 0, 0, 0, REQUEST_ROUTE|EVENT_ROUTE},
    {"test_check_uri",(cmd_function)w_test_check_uri,0, 0, 0, REQUEST_ROUTE|EVENT_ROUTE},
	
	{ 0, 0, 0, 0, 0, 0}
};

static param_export_t params[]={
	{"test_int_param",	    INT_PARAM,	    &int_param},
    {"test_str_param",      PARAM_STR,      &str_param},
	{0, 0, 0}
};

struct module_exports exports = {
	"xhttp_self",
	DEFAULT_DLFLAGS, /* dlopen flags */
	cmds,
	params,
	0,              /* exported RPC methods */
	0,         	    /* exported pseudo-variables */
	0,              /* response function */
	mod_init,       /* module initialization function */
	0,		        /* per child init function */
	mod_destroy     /* destroy function */
};

static int mod_init(void)
{
    LM_DBG("init\n");

    /* bind the XHTTP API */
	if (xhttp_load_api(&xhttp_api) < 0) {
		LM_ERR("cannot bind to XHTTP API\n");
		return -1;
	}

    testInit = malloc(10000);

	return 0;
}

static void mod_destroy(void)
{
	LM_DBG("cleaning up\n");

    free(testInit);
}

static int ki_test_dispatch(sip_msg_t* msg)
{
	int ret = 0;

	if(msg==NULL) {
		LM_ERR("No message\n");
		return -1;
	}

	if(!IS_HTTP(msg)) {
		LM_DBG("Got non HTTP msg\n");
		return NONSIP_MSG_PASS;
	}

    ret = self_handle(msg);
    if (ret < 0) {
		return -1;
	}

	return 0;
}

static int w_test_dispatch(sip_msg_t* msg)
{
	return ki_test_dispatch(msg);
}

static int w_test_check_uri(sip_msg_t* msg)
{
	if(msg==NULL) {
		LM_ERR("No message\n");
		return -1;
	}

	str *uri = &msg->first_line.u.request.uri;
	LM_DBG("URI: %.*s\n", uri->len, uri->s);
	
    if (0 == strncmp(uri->s, test_mod_uri.s, test_mod_uri.len))
    {
        LM_DBG("URI matches: %.*s\n", uri->len, uri->s);
		/* Return True */
		return 1;
    }

	/* Return False */
	LM_DBG("URI does not match: %.*s (%.*s)\n", uri->len, uri->s, test_mod_uri.len, test_mod_uri.s);
	return -1;
}

/**
 *
 */
/* clang-format off */
static sr_kemi_t sr_kemi_xhttp_self_exports[] = {
	{ str_init("xhttp_self"), str_init("dispatch"),
		SR_KEMIP_INT, ki_test_dispatch,
		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
	},

	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
};
/* clang-format on */

/**
 *
 */
int mod_register(char *path, int *dlflags, void *p1, void *p2)
{
	sr_kemi_modules_add(sr_kemi_xhttp_self_exports);
	return 0;
}

2.2、http请求处理入口

//处理入口
int self_handle(sip_msg_t* msg)
{
    str uri = {0, 0};
    str method = {0, 0};
    str body = {0, 0};

    //解析方法
    method.s = msg->first_line.u.request.method.s;
    method.len = msg->first_line.u.request.method.len;

    //解析url
    uri.s = msg->first_line.u.request.uri.s;
    uri.len = msg->first_line.u.request.uri.len;

    LM_BUG("method:%.*s\n", method.len, method.s);
    LM_BUG("uri:%.*s\n", uri.len, uri.s);
    
    //解析body
    body.s = get_body( msg );
	if(body.s == NULL)
	{
		LM_DBG("no message body\n");
	}
	body.len = msg->buf + msg->len - body.s;

    LM_DBG("body len=%d body:%.*s\n", body.len, body.len, body.s);

    //这里需要开始处理具体业务,省略

    char resp_body[1024];

    sprintf(resp_body, "int_param:%d\n str_param:%.*s\n Method:%.*s\n uri:%.*s\n body:%.*s\n",
                int_param,
                str_param.len, str_param.s,
                method.len, method.s,
                uri.len, uri.s,
                body.len, body.s);
    
    str str_reason = str_init("OK");
    str str_type = str_init("text/html");
    str str_body;
    str_body.s = resp_body;
    str_body.len = strlen(resp_body);

    //回复请求
    xhttp_api.reply(msg, 200, &str_reason, &str_type, &str_body);

    return 0;
}

2.3、编写Makefile

include ../../Makefile.defs
auto_gen=
NAME=xhttp_self.so
LIBS=

include ../../Makefile.modules
 

通过以上实现,一个自定义的http服务模块基本实现完成

 

3、配置文件加载模块和路由

loadmodule     "xhttp_self"    # 加载模块

modparam("xhttp_self", "test_int_param", 123456)    #设置参数
modparam("xhttp_self", "test_str_param", "abcdefg") #设置参数

event_route[xhttp:request] {
    set_reply_close();
    set_reply_no_connect();
    
    if (test_check_uri()){    #检测uri是否是需要处理的
        test_dispatch();        #处理请求
        exit;
    }

    xhttp_reply("200", "OK", "text/html",
                "<html><body>Wrong URL $hu</body></html>");
    exit;
}

4、验证接口

启动kamailio,通过curl调用接口测试

4.1、测试post请求

[root@vss-local-dev-001 home]# curl 127.0.0.1:18089/self/test_mod?abc=def -d "this is test body" -X POST
 int_param:123456
 str_param:abcdefg
 Method:POST
 uri:/self/test_mod?abc=def
 body:this is test body
[root@vss-local-dev-001 home]# 

程序打印:

59(30975) DEBUG: <core> [core/parser/msg_parser.c:555]: parse_headers(): Via found, flags=2
59(30975) DEBUG: <core> [core/parser/msg_parser.c:557]: parse_headers(): this is the first via
59(30975) DEBUG: xhttp_self [xhttp_self.c:165]: w_test_check_uri(): URI: /self/test_mod?abc=def
59(30975) DEBUG: xhttp_self [xhttp_self.c:169]: w_test_check_uri(): URI matches: /self/test_mod?abc=def
59(30975) BUG: xhttp_self [xhttp_self.c:96]: self_handle(): method:POST
59(30975) BUG: xhttp_self [xhttp_self.c:97]: self_handle(): uri:/self/test_mod?abc=def
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [User-Agent] type 28
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Host] type 0
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Accept] type 23
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Length] type 12
59(30975) DEBUG: <core> [core/parser/msg_parser.c:187]: get_hdr_field(): content_length=17
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Type] type 11
59(30975) DEBUG: <core> [core/parser/msg_parser.c:91]: get_hdr_field(): found end of header
59(30975) DEBUG: xhttp_self [xhttp_self.c:106]: self_handle(): body len=17 body:this is test body
59(30975) DEBUG: xhttp [xhttp_mod.c:416]: xhttp_send_reply(): response with content-type: text/html
59(30975) DEBUG: xhttp [xhttp_mod.c:424]: xhttp_send_reply(): response with body:  int_param:123456
 str_param:abcdefg
 Method:POST
 uri:/self/test_mod?abc=def
 body:this is test body

59(30975) DEBUG: xhttp [xhttp_mod.c:426]: xhttp_send_reply(): sending out response: 200 OK

4.2、测试get请求

[root@vss-local-dev-001 home]# curl 127.0.0.1:18089/self/test_mod?abc=def -d "this is test body" -X GET
 int_param:123456
 str_param:abcdefg
 Method:GET
 uri:/self/test_mod?abc=def
 body:this is test body
[root@vss-local-dev-001 home]# 

程序打印:

60(30976) DEBUG: <core> [core/parser/msg_parser.c:555]: parse_headers(): Via found, flags=2
60(30976) DEBUG: <core> [core/parser/msg_parser.c:557]: parse_headers(): this is the first via
60(30976) DEBUG: xhttp_self [xhttp_self.c:165]: w_test_check_uri(): URI: /self/test_mod?abc=def
60(30976) DEBUG: xhttp_self [xhttp_self.c:169]: w_test_check_uri(): URI matches: /self/test_mod?abc=def
60(30976) BUG: xhttp_self [xhttp_self.c:96]: self_handle(): method:GET
60(30976) BUG: xhttp_self [xhttp_self.c:97]: self_handle(): uri:/self/test_mod?abc=def
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [User-Agent] type 28
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Host] type 0
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Accept] type 23
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Length] type 12
60(30976) DEBUG: <core> [core/parser/msg_parser.c:187]: get_hdr_field(): content_length=17
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Type] type 11
60(30976) DEBUG: <core> [core/parser/msg_parser.c:91]: get_hdr_field(): found end of header
60(30976) DEBUG: xhttp_self [xhttp_self.c:106]: self_handle(): body len=17 body:this is test body
60(30976) DEBUG: xhttp [xhttp_mod.c:416]: xhttp_send_reply(): response with content-type: text/html
60(30976) DEBUG: xhttp [xhttp_mod.c:424]: xhttp_send_reply(): response with body:  int_param:123456
 str_param:abcdefg
 Method:GET
 uri:/self/test_mod?abc=def
 body:this is test body

60(30976) DEBUG: xhttp [xhttp_mod.c:426]: xhttp_send_reply(): sending out response: 200 OK

 通过上面两次打印结果也可以看出通过脚本modparam设置的变量的值

4.3、异常url测试

我们自定义模块的对应url路径为"/self/test_mod"开头,所以弄个不匹配的测试

例如 "/self/no_test_mod"

[root@vss-local-dev-001 home]# curl 127.0.0.1:18089/self/no_test_mod?abc=def -d "this is test body" -X GET
<html><body>Wrong URL /self/no_test_mod?abc=def</body></html>
[root@vss-local-dev-001 home]# 

程序打印:

53(30969) DEBUG: <core> [core/parser/msg_parser.c:555]: parse_headers(): Via found, flags=2
53(30969) DEBUG: <core> [core/parser/msg_parser.c:557]: parse_headers(): this is the first via
53(30969) DEBUG: xhttp_self [xhttp_self.c:165]: w_test_check_uri(): URI: /self/no_test_mod?abc=def
53(30969) DEBUG: xhttp_self [xhttp_self.c:175]: w_test_check_uri(): URI does not match: /self/no_test_mod?abc=def (/self/test_mod)
53(30969) DEBUG: xhttp [xhttp_mod.c:416]: xhttp_send_reply(): response with content-type: text/html
53(30969) DEBUG: xhttp [xhttp_mod.c:424]: xhttp_send_reply(): response with body: <html><body>Wrong URL /self/no_test_mod?abc=def</body></html>
53(30969) DEBUG: xhttp [xhttp_mod.c:426]: xhttp_send_reply(): sending out response: 200 OK

0条评论
0 / 1000
c****n
4文章数
0粉丝数
c****n
4 文章 | 0 粉丝
原创

如何在kamailio编写一个自定义的模块作为http服务

2024-08-07 09:33:48
28
0

1、主要结构说明

1.1、导出参数

模块对外提供的指定相关参数入口,主要kamailio脚本加载模块时指定初始化参数

对应结构如下:

typedef struct param_export {
	char* name;             /**< null terminated param. name */
	modparam_t type;        /**< param. type */
	void* param_pointer;    /**< pointer to the param. memory location */
} param_export_t;

参数说明:

name:导出到脚本中对应的参数名称

type:参数类型

param_pointer:程序内存储对应参数的指针

1.2、导出方法

模块对外提供的函数调用入口,主要是kamailio脚本处理对应业务时调用对应模块函数实现具体业务逻辑。

对应结构如下:

typedef 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; /**< function called to free the "fixed"
									   parameters */
	unsigned int flags;     /**< Function flags */
} cmd_export_t;

参数说明:

name:导出到脚本中对应的方法名

function:模块内对应的处理函数,一般函数返回值等于0表示成功,小于0表示失败

param_no:方法对应的参数个数

fixup:解析参数的方法

free_fixup:释放参数资源的方法

flag:描述导出方法可以在脚本内的哪段路由中被执行

flag可选值:

#define REQUEST_ROUTE (1 << 0)
#define FAILURE_ROUTE (1 << 1)
#define TM_ONREPLY_ROUTE (1 << 2)
#define BRANCH_ROUTE  (1 << 3)
#define ONSEND_ROUTE  (1 << 4)
#define ERROR_ROUTE   (1 << 5)
#define LOCAL_ROUTE   (1 << 6)
#define CORE_ONREPLY_ROUTE (1 << 7)
#define BRANCH_FAILURE_ROUTE (1 << 8)
#define ONREPLY_ROUTE (TM_ONREPLY_ROUTE|CORE_ONREPLY_ROUTE)
#define ONEVENT_ROUTE (1 << 9)
#define EVENT_ROUTE   (REQUEST_ROUTE|ONEVENT_ROUTE)
#define ANY_ROUTE     (0xFFFFFFFF)

1.3、导出模块

对应脚本内调用的模块信息

对应结构如下:

typedef struct module_exports {
	/**< null terminated module name */
	char* name;
	/**< flags for dlopen  */
	unsigned int dlflags;
	/**< null terminated array of the exported commands (config functions)*/
	cmd_export_t* cmds;
	/**< null terminated array of the exported module parameters */
	param_export_t* params;
	/**< null terminated array of exported rpc methods */
	rpc_export_t* rpc_methods;
	/*!< null terminated array of the exported module items (pseudo-variables) */
	pv_export_t* pv_items;
	/**< function used for responses, returns yes or no; can be null */
	response_function response_f;
	/**< Initialization function */
	init_function init_mod_f;
	/**< function called by all processes after the fork */
	child_init_function init_child_f;
	/**< function called when the module is "destroyed" (on server shut down) */
	destroy_function destroy_mod_f;
} module_exports_t;

主要参数说明:

name:模块名

cmds:导出的方法

params:导出的参数

init_mod_f:初始化函数

init_child_f:模块在每个子进程中的初始化函数

destroy_mod_f:模块销毁时的处理函数

2、http服务模块编写

2.1、编写模块基本结构

static str test_mod_uri = str_init("/self/test_mod");

static int w_test_dispatch(sip_msg_t* msg);
static int w_test_check_uri(sip_msg_t* msg);
static int mod_init(void);
static void mod_destroy(void);

//需要用http_api接口对收到的请求做响应操作
xhttp_api_t         xhttp_api; 

int int_param           = 0; 
str str_param     = STR_NULL;


void* testInit = NULL;

/* module commands */
static cmd_export_t cmds[] = {
	{"test_dispatch", (cmd_function)w_test_dispatch, 0, 0, 0, REQUEST_ROUTE|EVENT_ROUTE},
    {"test_check_uri",(cmd_function)w_test_check_uri,0, 0, 0, REQUEST_ROUTE|EVENT_ROUTE},
	
	{ 0, 0, 0, 0, 0, 0}
};

static param_export_t params[]={
	{"test_int_param",	    INT_PARAM,	    &int_param},
    {"test_str_param",      PARAM_STR,      &str_param},
	{0, 0, 0}
};

struct module_exports exports = {
	"xhttp_self",
	DEFAULT_DLFLAGS, /* dlopen flags */
	cmds,
	params,
	0,              /* exported RPC methods */
	0,         	    /* exported pseudo-variables */
	0,              /* response function */
	mod_init,       /* module initialization function */
	0,		        /* per child init function */
	mod_destroy     /* destroy function */
};

static int mod_init(void)
{
    LM_DBG("init\n");

    /* bind the XHTTP API */
	if (xhttp_load_api(&xhttp_api) < 0) {
		LM_ERR("cannot bind to XHTTP API\n");
		return -1;
	}

    testInit = malloc(10000);

	return 0;
}

static void mod_destroy(void)
{
	LM_DBG("cleaning up\n");

    free(testInit);
}

static int ki_test_dispatch(sip_msg_t* msg)
{
	int ret = 0;

	if(msg==NULL) {
		LM_ERR("No message\n");
		return -1;
	}

	if(!IS_HTTP(msg)) {
		LM_DBG("Got non HTTP msg\n");
		return NONSIP_MSG_PASS;
	}

    ret = self_handle(msg);
    if (ret < 0) {
		return -1;
	}

	return 0;
}

static int w_test_dispatch(sip_msg_t* msg)
{
	return ki_test_dispatch(msg);
}

static int w_test_check_uri(sip_msg_t* msg)
{
	if(msg==NULL) {
		LM_ERR("No message\n");
		return -1;
	}

	str *uri = &msg->first_line.u.request.uri;
	LM_DBG("URI: %.*s\n", uri->len, uri->s);
	
    if (0 == strncmp(uri->s, test_mod_uri.s, test_mod_uri.len))
    {
        LM_DBG("URI matches: %.*s\n", uri->len, uri->s);
		/* Return True */
		return 1;
    }

	/* Return False */
	LM_DBG("URI does not match: %.*s (%.*s)\n", uri->len, uri->s, test_mod_uri.len, test_mod_uri.s);
	return -1;
}

/**
 *
 */
/* clang-format off */
static sr_kemi_t sr_kemi_xhttp_self_exports[] = {
	{ str_init("xhttp_self"), str_init("dispatch"),
		SR_KEMIP_INT, ki_test_dispatch,
		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
	},

	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
};
/* clang-format on */

/**
 *
 */
int mod_register(char *path, int *dlflags, void *p1, void *p2)
{
	sr_kemi_modules_add(sr_kemi_xhttp_self_exports);
	return 0;
}

2.2、http请求处理入口

//处理入口
int self_handle(sip_msg_t* msg)
{
    str uri = {0, 0};
    str method = {0, 0};
    str body = {0, 0};

    //解析方法
    method.s = msg->first_line.u.request.method.s;
    method.len = msg->first_line.u.request.method.len;

    //解析url
    uri.s = msg->first_line.u.request.uri.s;
    uri.len = msg->first_line.u.request.uri.len;

    LM_BUG("method:%.*s\n", method.len, method.s);
    LM_BUG("uri:%.*s\n", uri.len, uri.s);
    
    //解析body
    body.s = get_body( msg );
	if(body.s == NULL)
	{
		LM_DBG("no message body\n");
	}
	body.len = msg->buf + msg->len - body.s;

    LM_DBG("body len=%d body:%.*s\n", body.len, body.len, body.s);

    //这里需要开始处理具体业务,省略

    char resp_body[1024];

    sprintf(resp_body, "int_param:%d\n str_param:%.*s\n Method:%.*s\n uri:%.*s\n body:%.*s\n",
                int_param,
                str_param.len, str_param.s,
                method.len, method.s,
                uri.len, uri.s,
                body.len, body.s);
    
    str str_reason = str_init("OK");
    str str_type = str_init("text/html");
    str str_body;
    str_body.s = resp_body;
    str_body.len = strlen(resp_body);

    //回复请求
    xhttp_api.reply(msg, 200, &str_reason, &str_type, &str_body);

    return 0;
}

2.3、编写Makefile

include ../../Makefile.defs
auto_gen=
NAME=xhttp_self.so
LIBS=

include ../../Makefile.modules
 

通过以上实现,一个自定义的http服务模块基本实现完成

 

3、配置文件加载模块和路由

loadmodule     "xhttp_self"    # 加载模块

modparam("xhttp_self", "test_int_param", 123456)    #设置参数
modparam("xhttp_self", "test_str_param", "abcdefg") #设置参数

event_route[xhttp:request] {
    set_reply_close();
    set_reply_no_connect();
    
    if (test_check_uri()){    #检测uri是否是需要处理的
        test_dispatch();        #处理请求
        exit;
    }

    xhttp_reply("200", "OK", "text/html",
                "<html><body>Wrong URL $hu</body></html>");
    exit;
}

4、验证接口

启动kamailio,通过curl调用接口测试

4.1、测试post请求

[root@vss-local-dev-001 home]# curl 127.0.0.1:18089/self/test_mod?abc=def -d "this is test body" -X POST
 int_param:123456
 str_param:abcdefg
 Method:POST
 uri:/self/test_mod?abc=def
 body:this is test body
[root@vss-local-dev-001 home]# 

程序打印:

59(30975) DEBUG: <core> [core/parser/msg_parser.c:555]: parse_headers(): Via found, flags=2
59(30975) DEBUG: <core> [core/parser/msg_parser.c:557]: parse_headers(): this is the first via
59(30975) DEBUG: xhttp_self [xhttp_self.c:165]: w_test_check_uri(): URI: /self/test_mod?abc=def
59(30975) DEBUG: xhttp_self [xhttp_self.c:169]: w_test_check_uri(): URI matches: /self/test_mod?abc=def
59(30975) BUG: xhttp_self [xhttp_self.c:96]: self_handle(): method:POST
59(30975) BUG: xhttp_self [xhttp_self.c:97]: self_handle(): uri:/self/test_mod?abc=def
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [User-Agent] type 28
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Host] type 0
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Accept] type 23
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Length] type 12
59(30975) DEBUG: <core> [core/parser/msg_parser.c:187]: get_hdr_field(): content_length=17
59(30975) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Type] type 11
59(30975) DEBUG: <core> [core/parser/msg_parser.c:91]: get_hdr_field(): found end of header
59(30975) DEBUG: xhttp_self [xhttp_self.c:106]: self_handle(): body len=17 body:this is test body
59(30975) DEBUG: xhttp [xhttp_mod.c:416]: xhttp_send_reply(): response with content-type: text/html
59(30975) DEBUG: xhttp [xhttp_mod.c:424]: xhttp_send_reply(): response with body:  int_param:123456
 str_param:abcdefg
 Method:POST
 uri:/self/test_mod?abc=def
 body:this is test body

59(30975) DEBUG: xhttp [xhttp_mod.c:426]: xhttp_send_reply(): sending out response: 200 OK

4.2、测试get请求

[root@vss-local-dev-001 home]# curl 127.0.0.1:18089/self/test_mod?abc=def -d "this is test body" -X GET
 int_param:123456
 str_param:abcdefg
 Method:GET
 uri:/self/test_mod?abc=def
 body:this is test body
[root@vss-local-dev-001 home]# 

程序打印:

60(30976) DEBUG: <core> [core/parser/msg_parser.c:555]: parse_headers(): Via found, flags=2
60(30976) DEBUG: <core> [core/parser/msg_parser.c:557]: parse_headers(): this is the first via
60(30976) DEBUG: xhttp_self [xhttp_self.c:165]: w_test_check_uri(): URI: /self/test_mod?abc=def
60(30976) DEBUG: xhttp_self [xhttp_self.c:169]: w_test_check_uri(): URI matches: /self/test_mod?abc=def
60(30976) BUG: xhttp_self [xhttp_self.c:96]: self_handle(): method:GET
60(30976) BUG: xhttp_self [xhttp_self.c:97]: self_handle(): uri:/self/test_mod?abc=def
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [User-Agent] type 28
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Host] type 0
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Accept] type 23
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Length] type 12
60(30976) DEBUG: <core> [core/parser/msg_parser.c:187]: get_hdr_field(): content_length=17
60(30976) DEBUG: <core> [core/parser/parse_hname2.c:301]: parse_sip_header_name(): parsed header name [Content-Type] type 11
60(30976) DEBUG: <core> [core/parser/msg_parser.c:91]: get_hdr_field(): found end of header
60(30976) DEBUG: xhttp_self [xhttp_self.c:106]: self_handle(): body len=17 body:this is test body
60(30976) DEBUG: xhttp [xhttp_mod.c:416]: xhttp_send_reply(): response with content-type: text/html
60(30976) DEBUG: xhttp [xhttp_mod.c:424]: xhttp_send_reply(): response with body:  int_param:123456
 str_param:abcdefg
 Method:GET
 uri:/self/test_mod?abc=def
 body:this is test body

60(30976) DEBUG: xhttp [xhttp_mod.c:426]: xhttp_send_reply(): sending out response: 200 OK

 通过上面两次打印结果也可以看出通过脚本modparam设置的变量的值

4.3、异常url测试

我们自定义模块的对应url路径为"/self/test_mod"开头,所以弄个不匹配的测试

例如 "/self/no_test_mod"

[root@vss-local-dev-001 home]# curl 127.0.0.1:18089/self/no_test_mod?abc=def -d "this is test body" -X GET
<html><body>Wrong URL /self/no_test_mod?abc=def</body></html>
[root@vss-local-dev-001 home]# 

程序打印:

53(30969) DEBUG: <core> [core/parser/msg_parser.c:555]: parse_headers(): Via found, flags=2
53(30969) DEBUG: <core> [core/parser/msg_parser.c:557]: parse_headers(): this is the first via
53(30969) DEBUG: xhttp_self [xhttp_self.c:165]: w_test_check_uri(): URI: /self/no_test_mod?abc=def
53(30969) DEBUG: xhttp_self [xhttp_self.c:175]: w_test_check_uri(): URI does not match: /self/no_test_mod?abc=def (/self/test_mod)
53(30969) DEBUG: xhttp [xhttp_mod.c:416]: xhttp_send_reply(): response with content-type: text/html
53(30969) DEBUG: xhttp [xhttp_mod.c:424]: xhttp_send_reply(): response with body: <html><body>Wrong URL /self/no_test_mod?abc=def</body></html>
53(30969) DEBUG: xhttp [xhttp_mod.c:426]: xhttp_send_reply(): sending out response: 200 OK

文章来自个人专栏
kamailio/opensips
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0