asterisk应用模块app开发

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

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

代码以下:函数

#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目录下ui

CLI>module load app_helloworld.sospa

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

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

asterisk里提供了大量的app用于在extension.conf中编写dialplan,这些app很是丰富,你几乎能够作任何事情,你甚至能够在dialplan中设置变量,使用一些简单的流程控制等。可是当你发现你须要的app在asterisk里并无提供,而老板又每天催你交差的时候,你就不得不本身来实现它,建议你们把本身实现的app放在一个新的模块里,好比咱们能够创建一个新的名为app_myapps.so的模块,那么这就又牵涉到如何添加一个新的模块。 ip

    首先,除了一些内建的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); rem

    那么内建的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这个模块的.

相关文章
相关标签/搜索