bacnet协议:asterisk 应用模块app的开发

来源:百度文库 编辑:中财网 时间:2024/04/28 11:37:26

我的第一个asterisk内部模块,”hello world~”
首先配置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的模块,那么这就又牵涉到如何添加一个新的模块。 $*w]]b$Dn
首先,除了一些内建的app以外,所有的app都是在模块中定义的,当这个模块载入后,模块中定义的app会注册到asterisk中,这些app被按照字母序放在一个链表中,asterisk中习惯用以下宏初始化一个全局链表: rDFD rviW_

复制代码

  1. #define AST_LIST_HEAD_STATIC(name, type)
  2. struct name {
  3. struct type *first;
  4. struct type *last;
  5. ast_mutex_t lock;
  6. } name;

1><@$kVMm~
比如初始化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结构体(今后会详细介绍chan_sip.c,现在看不明白也没有关系),然后调用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,这就是分层的好处。 -OV:y],-
好了,现在言归正传,一个模块文件要放在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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//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");

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

 

Comments