pbx.c主要实现了builtin applications,也就是内置的应用,比如最常见的Answer,Hangup, Background,Wait等等。
在/main/asterisk.c中有一段代码调用load_pbx()负责加载builtin applications。
这个load_pbx()函数就是实现在pbx.c中,它的主要任务是遍历全局数组builtins中每个application信息,调用ast_register_application()注册application的各自入口函数。
06046 /* Register builtin applications */
06047 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06048 if (option_verbose)
06049 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06050 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06051 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06052 return -1;
06053 }
06054 }
比如Hangup应用的入口函数就是pbx_builtin_hangup()
00364 { "Hangup", pbx_builtin_hangup,
00365 "Hang up the calling channel",
00366 " Hangup([causecode]): This application will hang up the calling channel.\n"
00367 "If a causecode is given the channel's hangup cause will be set to the given\n"
00368 "value.\n"
00369 },
下面我们分析一下pbx_builtin_hangup()函数,这个函数查看参数data调用ast_str2cause()获取挂断码,如果没有获取到,则设置chan->hangupcause为
AST_CAUSE_NORMAL_CLEARING,也就是0。
05448 /*!
05449 * \ingroup applications
05450 */
05451 static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
05452 {
05453 if (!ast_strlen_zero(data)) {
05454 int cause;
05455 char *endptr;
05456
05457 if ((cause = ast_str2cause(data)) > -1) {
05458 chan->hangupcause = cause;
05459 return -1;
05460 }
05461
05462 cause = strtol((const char *) data, &endptr, 10);
05463 if (cause != 0 || (data != endptr)) {
05464 chan->hangupcause = cause;
05465 return -1;
05466 }
05467
05468 ast_log(LOG_NOTICE, "Invalid cause given to Hangup(): \"%s\"\n", (char *) data);
05469 }
05470
05471 if (!chan->hangupcause) {
05472 chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
05473 }
05474
05475 return -1;
05476 }
看看pbx_exec()函数,这个函数是所有application被调用的入口处。它首先保存channel的两个变量,appl和data,分别表示正在调用的application名和参数。然后调用app->execute(c, data)进入真正的处理,完后恢复appl和data的值,有点像堆栈的管理
00507 /*
00508 \note This function is special. It saves the stack so that no matter
00509 how many times it is called, it returns to the same place */
00510 int pbx_exec(struct ast_channel *c, /*!< Channel */
00511 struct ast_app *app, /*!< Application */
00512 void *data) /*!< Data for execution */
00513 {
00514 int res;
00515
00516 const char *saved_c_appl;
00517 const char *saved_c_data;
00518
00519 if (c->cdr && !ast_check_hangup(c))
00520 ast_cdr_setapp(c->cdr, app->name, data);
00521
00522 /* save channel values */
00523 saved_c_appl= c->appl;
00524 saved_c_data= c->data;
00525
00526 c->appl = app->name;
00527 c->data = data;
00528 /* XXX remember what to to when we have linked apps to modules */
00529 if (app->module) {
00530 /* XXX LOCAL_USER_ADD(app->module) */
00531 }
00532 res = app->execute(c, data);
00533 if (app->module) {
00534 /* XXX LOCAL_USER_REMOVE(app->module) */
00535 }
00536 /* restore channel values */
00537 c->appl = saved_c_appl;
00538 c->data = saved_c_data;
00539 return res;
00540 }