asterisk模块编写
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
你已经可以在 Asterisk 模块中添加 CDR 处理了!
Asterisk 模块编写 3--高级
下面是通过基本接口来为 Asterisk 提供更多功能系列文章的第三篇--Asterisk 模块编写 3--高
级。
第一篇《Asterisk 模块编写 1--入门》
第二篇《Asterisk 模块编写 2--进阶》
Asterisk 模块编写 1--入门
作者/ Russell Bryant 翻译/ 高志
是否有过想编写 Asterisk 模块的想法?在 Asterisk 中有的模块相当的复杂,但是其结构
却非常的简单,让我们来从“Hello World”Asterisk 模块开始:res_helloworld.该模块是基于
相反的,unload_module 的工作是“ Hello Asterisk, again. I’m about to disappear, so please don’t use any of these features that I was providing to you anymore. If you do, you’ll explode. kthx! ”
重新编译 Asterisk,编译系统将自动发现该模块,该模块像其他模块一样,也会被编译,
最后安装。通过编译,安装,运行 Asterisk,这时可以确认你的模块是否被正确的加载: *CLI> module show like helloworld Module Description Use Count res_helloworld.so Hello World 0 1 modules loaded
下面这小段代码表示至少给函数提供了一个参数。值得注意的是,这里的 ast_cli_entry 参数用于检索多少命令本身定义的参数和 ast_cli_args 参数用于检索多少参数,实际上是在 CLI 命令行下执行此命令时指定的。如果它们相等,那么就能提供简单的“echo”。
if (a->argc == e->args) { ast_cli(a->fd, "You did not provide an argument to echo\n\n"); return CLI_SHOWUSAGE;
让我们继续进行同时包含使用 Asteisk 日志模块接口,用于显示 Asterisk 日志信息,显
示日志信息也是本模块所要做的事情。 #include "asterisk/logger.h"
现在包含每个 Asterisk 模块必须的使用的两个函数,load_module()和 unload_module().
这个 CLI 处理程序相匹配的 CLI 命令处理程序定义的函数原型。ast_cli_entry 参数包括 有关 CLI 命令正在执行的静态信息。当 CLI 命令非正常执行其他调用的时候,会设置 cmd 参 数。该 ast_cli_args 参数包含这一命令一次执行的特定信息,如同命令参数。
static char *handle_cli_echo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Core 。
*CLI> cdr show status ... CDR registered backend: HelloWorld
…
当你挂电话,将会看到 CDR 处理被执行。
[Jun 20 18:08:29] NOTICE[4922]: res_helloworld.c:36 cdr_helloworld: We got a CDR for channel ‘SIP/5001-007e9da8′. Source: ‘5001′, Dest: ‘586′, Duration: 1
作者/ Russell Bryant 翻译/ 高志
在 res_helloworld.c 中,我们应用了 load_module 和 unload_module 函数。在那个模块中, 我们仅仅是打印日志,其实在该模块中可以实现更多的功能。 load_module 的工作是说:“hello Asterisk, I’m a module. I can provide some features to Asterisk and here is how you use them."
在本文里,你将看到如何实现一个 Asterisk CLI 命令。CLI 命令对于显示配置信息、统
计信息和其它调试目的来说都是非常有用的。我们继续编辑上一篇文章中的那个
res_helloworld2.c。
第一步是加载定义 CLI 命令接口的头文件: #include "asterisk/cli.h"
下面是实现 CLI 命令“echo”的代码,简单地打印了 CLI 命令的第一个参数,后面会解释
"Usage: echo <stuff>\n" " Print back the first argument.\n" "Examples:\n" " echo foo\n" " echo \"multiple words\"\n" ""; return NULL; case CLI_GENERATE: return NULL; }
Asterisk1.6 的,为 Asterisk1.4 编写模块几乎一样。创建的文件名为 res_helloworld.c,存放在
Asterisk 的源代码树/res 目录下。
首先每个 Asterisk 模块都包含主要的 Asterisk 头文件,asterisk.h #include "asterisk.h“
接下来,包含 ASTERISK_FILE_VERSION 宏,该宏用于注册该文件的版本,通过 CLI
命令“core show file version like filename”命令查看文件 SVN 版本。
包含 Asterisk 模块头文件,包含该头文件是定义实现 Asterisk 模块所必须的。 #include "asterisk/module.h"
在函数的开头 switch 语句是用来处理 cmd 参数,以指示调用什么功能。有两种情况需 要处理: CLI_INIT. 每个 CLI 命令处理程序都要执行一次 CLI_INIT. 用来要求函数说明命令是什么, 用法是什么等。 CLI_GENERATE. This cmd is used for implementing tab completion. CLI commands that provide tab completion of arguments must add code here. Implementing tab completion may be explained in a later tutorial. For now, there are many examples throughout the code.
[Jun 19 10:51:05] NOTICE[26612]: res_helloworld.c:42 load_module: Hello World! Loaded res_helloworld.so => (Hello World) 祝贺你,你已经成功的完成了 Asteisk 模块编写! 下一步,我们将开始实现在 Asteirsk 模块中更有用的应用。请看下一篇《Asterisk 模块 编写 2—进阶》。 上一篇文章《Asterisk 模块编写入门》里已经解释了 Hello World Asterisk 模块。该模块只实 现了能够给 Asterisk 编译,能够加载到 Asteisk 中去,当被加载或卸载时打印简单的日志信 息。现在让该模块做些更有意义的事情。
最后,每个模块必须包含 AST_MODULE_INFO 宏实例。该宏包含模块必要代码是用
于该模块被加载时向 Asterisk core 注册自己。 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hello World");
最终的结果构成 res_helloworld.c 文件。
ast_log(LOG_NOTICE, "We got a CDR for channel '%s'. " "Source: '%s', Dest: '%s', Duration: %ld\n", cdr->channel, cdr->src, cdr->dst, cdr->duration);
return 0; }
接下来,将刚刚实现的应用通过 load_module() 和 unload_module() 函数经新功能添加到 该模块中去。
在 load_module() 函数中,将增加一个函数调用用于向 Asterisk Core 注册该 CDR 处理。 参数是该应用的名称,简短的描述,以及当 CDR post 时 Asterisk Core 调用函数。
通过 CLI 命令可以自己卸载、加载你的模块,可以观测到日志信息。 *CLI> module unload res_helloworld.so
[Jun 19 10:50:57] NOTICE[26612]: res_helloworld.c:35 unload_module: Goodbye World! *CLI> module load res_helloworld.so
} 最后,我们打印一个参数到 CLI,返回 CLI 命令成功执行的结果。 ast_cli(a->fd, "%s\n", a->argv[1]); return CLI_SUCCESS; 下一步增加包含在这个模块里的 CLI 命令表。我们将使用 AST_CLI_DEFINE() 为表增 加单个入口。 AST_CLI_DEFINE 包含了 CLI 命令处理函数的指针,以及这个命令时用来做 什么的总结。 static struct ast_cli_entry cli_helloworld[] = {
ast_cdr_register("HelloWorld", "Hello World CDR Handler", cdr_helloworld); 在 unload_module() 中,需要对刚刚添加的应用注销。
ast_cdr_unregister("HelloWorld");
编译安装后,运行 Asterisk ,可以去确认你的新 CDR 应用是否被注册到了 Asterisk
这个功能。 复制代码 static char *handle_cli_echo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) {
switch (cmd) { case CLI_INIT:
e->command = "echo"; e->usage =
现在是更新模块提供功能给 Asterisk 的时候了。我们将从 CDR 处理开始,CDR 接口不 算是一个非常简单的应用。首先是添加合适的头文件。
#include "asterisk/cdr.h" 然后,我们增加一个新的函数,该函数在每次 CDR post 时将会调用,参数是 CDR 本 身。
static int cdr_helloworld(struct ast_cdr *cdr) {
当 Asterisk 加载和卸载模块时会调用他们。 static int load_module(void) { ast_log(LOG_NOTICE, "Hello World!\n"); return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { ast_log(LOG_NOTICE, "Goodbye World!\n"); return 0; } static int unload_module(void) { ast_log(LOG_NOTICE, "Goodbye World!\n"); return 0; }
if (a->argc == e->args) { ast_cli(a->fd, "You did not provide an argument to echo\n\n"); return CLI_SHOWUSAGE;
}wk.baidu.com
ast_cli(a->fd, "%s\n", a->argv[1]);
return CLI_SUCCESS; }