asterisk应用模块app开发

首先配置linux的开发环境及asterisk的源码.

创建的文件名为app_helloworld.c,存放在Asterisk的源代码树/apps目录下

代码如下:

#include "asterisk.h"             //每个Asterisk模块都包含主要的Asterisk头文件
#include "asterisk/module.h"      //包含ASTERISK_FILE_VERSION宏,该宏用于注册该文件的版本#include "asterisk/logger.h" 
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 100001 $")//该宏用于注册该文件的版本
static int load_module(void)         //Asterisk加载和卸载模块时会调用他们
{
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;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hello World");

编绎成功后,将app_helloworld.so 拷贝到 /usr/lib/asterisk/modules目录下

CLI>module load app_helloworld.so

CLI>Loaded app_helloworld.so => (Hello World)

装载成功,这只是个空的模块,下面我们添加些应用。 

asterisk里提供了大量的app用于在extension.conf中编写dialplan,这些app非常丰富,你几乎可以做任何事情,你甚至可以在dialplan中设置变量,使用一些简单的流程控制等。但是当你发现你需要的app在asterisk里并没有提供,而老板又天天催你交差的时候,你就不得不自己来实现它,建议大家把自己实现的app放在一个新的模块里,比如我们可以建立一个新的名为app_myapps.so的模块,那么这就又牵涉到如何添加一个新的模块。 

    首先,除了一些内建的app以外,所有的app都是在模块中定义的,当这个模块载入后,模块中定义的app会注册到asterisk中,这些app被按照字母序放在一个链表中,asterisk中习惯用以下宏初始化一个全局链表: 

#define AST_LIST_HEAD_STATIC(name, type) 
struct name 
{
    struct type *first; 
    struct type *last; 
    ast_mutex_t lock; 
} name;

    比如初始化apps链表:static AST_LIST_HEAD_STATIC(apps, ast_app); 

    那么内建的app在哪里定义的?main/pbx.c 

    在这个文件中定义了很多内建命令,比如answer, hangup, busy, backgroud等,在load_pbx()函数中被注册,正是这些在pbx中定义的built-in使得asterisk可以同时使用各种协议(sip, h323, iax2, zaptel, gtalk等),成为一个类似协议转换器的东西,而且也有公司确实就拿blackfin下移植的asterisk做了pstn网关产品,asterisk 具有分层的结构,在pbx层处理一些通用的共性的操作,然后根据channel的不同,调用相关的回调函数,来实现对不同协议的处理。现在以answer 为例来说明一下:

    假设context如下:

         exten => s, 1, Answer() 

         exten => s, 2, Echo() 

    当有呼叫进入时,在do_monitor线程中sipsock_read获得Invite消息,然后handle_request函数调用 handle_request_invite函数处理这个Invite消息,如果这是一个新的dialog,那么调用sip_new函数会返回一个 ast_channel结构体,然后调用ast_pbx_start,在 pbx_thread线程中调用__ast_pbx_run,然后调用ast_spawn_extension,再调用 pbx_extension_help,在这个函数中,会调用pbx_findapp()来根据extension中的app名查找对应的处理函数,在这个例子中,会找到pbx_builtin_answer,这个函数的第一个参数是一个channel结构体,这里此ast_channel是一个sip channel,那么它调用的answer函数其实就是chan_sip.so中定义的sip_answer()函数,现在大家明白了吧,对于pbx层来说,他根本就不需要知道是哪个channel,这就是分层的好处。

    好了,现在言归正传,一个模块文件要放在apps目录下,并用app_作为文件名的前缀,这里我们在apps目录下建立一个名为app_myapps.c 的新文件。其实添加一个新的模块和app非常的简单,那么一个模块需要哪些必备的要素呢?一般来说load_module()和 unload_module()这两个函数都是必须的,load_module()在载入这个模块时会被调用,所以我们要在这个函数里对app进行注册;在unload_module()时我们需要注销这个app并强制挂断所有正在使用这个模块的用户。那么下面就给出一个创建模块和新的app的代码模版吧: 

#include "asterisk.h" 
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.1 $") 
//这里是asterisk core用来控制源码文件的版本的 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <stdio.h> 
#include <asterisk/lock.h> 
#include <asterisk/file.h> 
#include <asterisk/logger.h> 
#include <asterisk/channel.h> 
#include <asterisk/pbx.h> 
#include <asterisk/options.h> 
#include <asterisk/config.h>
#include <asterisk/module.h> 
#include <asterisk/enum.h> 
#include <asterisk/utils.h> 
#include <asterisk/app.h> 
//to add any include files you need here 
static char *tdesc = "This is my app :)"; 
static char *app = "myapp"; 
static char *synopsis = "myapp(param1|param2):\n" 
                "This Application will do something, urr?\n"; 
static int myapp_exec(struct ast_channel *chan, void *data) 
{ 
    int res=0; 
    char *parse; 
    AST_DECLARE_APP_ARGS(args, 
 AST_APP_ARG(param1); 
 AST_APP_ARG(param2); 
    ); 
struct ast_module_user *u; 
if (ast_strlen_zero(data)) 
{ 
ast_log(LOG_WARNING, "MYAPP requires an argument (param1|param2)\n"); 
return -1; 
} 
u = ast_module_user_add(chan); 
parse = ast_strdupa(data); 
AST_STANDARD_APP_ARGS(args, parse); 
if (ast_strlen_zero(args.param1) ||  ast_strlen_zero(args.param2)) 
{ 
ast_log(LOG_WARNING, "MYAPP requires an argument (callee|filename)\n"); 
res = -1; 
goto out1; 
} 
/* 
 * to do anything you want to here, params are args.param1 and args.param2. 
 */ 
out1: 
    ast_module_user_remove(u); 
    return res; 
} 
static int load_module(void) 
{ 
    return ast_register_application(app, myapp_exec, synopsis, tdesc);   
} 
static int unload_module(void) 
{ 
    int res; 
    res = ast_unregister_application(app); 
    ast_module_user_hangup_all(); 
    return res; 
} 
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "MY OWN APPS");

好了,一个名叫myapp的extension应用就写好了,你可以给他传两个参数,参数之间用|隔开,如果你没有修改modules.conf的话,编译后重新启动一次asterisk会自动加载app_myapps.so这个模块的.


转载于:https://my.oschina.net/u/1537782/blog/222297

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值