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這個模塊的.

相關文章
相關標籤/搜索