diff --git a/apps/app_dial.c b/apps/app_dial.c index 238ed66e9e..c1dd67038c 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1874,7 +1874,11 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags if (gosub_args) { res9 = pbx_exec(peer, theapp, gosub_args); if (!res9) { - ast_pbx_run(peer); + struct ast_pbx_args args; + /* A struct initializer fails to compile for this case ... */ + memset(&args, 0, sizeof(args)); + args.no_hangup_chan = 1; + ast_pbx_run_args(peer, &args); } ast_free(gosub_args); if (option_debug) @@ -2224,7 +2228,7 @@ static int load_module(void) if (!con) ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n"); else - ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_dial"); + ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial"); res = ast_register_application(app, dial_exec, synopsis, descrip); res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip); diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index 68bf0ccee1..6e072bd6e7 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -262,6 +262,37 @@ enum ast_pbx_result ast_pbx_start(struct ast_channel *c); */ enum ast_pbx_result ast_pbx_run(struct ast_channel *c); +/*! + * \brief Options for ast_pbx_run() + */ +struct ast_pbx_args { + union { + /*! Pad this out so that we have plenty of room to add options + * but still maintain ABI compatibility over time. */ + uint64_t __padding; + struct { + /*! Do not hangup the channel when the PBX is complete. */ + unsigned int no_hangup_chan:1; + }; + }; +}; + +/*! + * \brief Execute the PBX in the current thread + * + * \param c channel to run the pbx on + * \param args options for the pbx + * + * This executes the PBX on a given channel. It allocates a new + * PBX structure for the channel, and provides all PBX functionality. + * See ast_pbx_start for an asynchronous function to run the PBX in a + * new thread as opposed to the current one. + * + * \retval Zero on success + * \retval non-zero on failure + */ +enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args); + /*! * \brief Add and extension to an extension context. * diff --git a/main/pbx.c b/main/pbx.c index 04146495da..763af44efe 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -288,7 +288,6 @@ static int pbx_builtin_background(struct ast_channel *, void *); static int pbx_builtin_wait(struct ast_channel *, void *); static int pbx_builtin_waitexten(struct ast_channel *, void *); static int pbx_builtin_incomplete(struct ast_channel *, void *); -static int pbx_builtin_keepalive(struct ast_channel *, void *); static int pbx_builtin_resetcdr(struct ast_channel *, void *); static int pbx_builtin_setamaflags(struct ast_channel *, void *); static int pbx_builtin_ringing(struct ast_channel *, void *); @@ -581,12 +580,6 @@ static struct pbx_builtin { "in order to receive DTMF.\n" }, - { "KeepAlive", pbx_builtin_keepalive, - "returns AST_PBX_KEEPALIVE value", - " KeepAlive(): This application is chiefly meant for internal use with Gosubs.\n" - "Please do not run it alone from the dialplan!\n" - }, - { "NoOp", pbx_builtin_noop, "Do Nothing (No Operation)", " NoOp(): This application does nothing. However, it is useful for debugging\n" @@ -722,7 +715,6 @@ static struct pbx_builtin { " Optionally, specify the class for music on hold within parenthesis.\n" "See Also: Playback(application), Background(application).\n" }, - }; static struct ast_context *contexts; @@ -3662,7 +3654,8 @@ static int collect_digits(struct ast_channel *c, int waittime, char *buf, int bu return 0; } -static int __ast_pbx_run(struct ast_channel *c) +static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, + struct ast_pbx_args *args) { int found = 0; /* set if we find at least one match */ int res = 0; @@ -3875,11 +3868,18 @@ static int __ast_pbx_run(struct ast_channel *c) } } } - if (!found && !error) + + if (!found && !error) { ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); - if (res != AST_PBX_KEEPALIVE) + } + + if (!args || !args->no_hangup_chan) { ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); - if ((res != AST_PBX_KEEPALIVE) && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { + } + + if ((!args || !args->no_hangup_chan) && + !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && + ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { set_ext_pri(c, "h", 1); while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { c->priority++; @@ -3894,8 +3894,11 @@ static int __ast_pbx_run(struct ast_channel *c) ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ pbx_destroy(c->pbx); c->pbx = NULL; - if (res != AST_PBX_KEEPALIVE) + + if (!args || !args->no_hangup_chan) { ast_hangup(c); + } + return 0; } @@ -3985,7 +3988,7 @@ static void *pbx_thread(void *data) */ struct ast_channel *c = data; - __ast_pbx_run(c); + __ast_pbx_run(c, NULL); decrease_call_count(); pthread_exit(NULL); @@ -4015,19 +4018,26 @@ enum ast_pbx_result ast_pbx_start(struct ast_channel *c) return AST_PBX_SUCCESS; } -enum ast_pbx_result ast_pbx_run(struct ast_channel *c) +enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args) { enum ast_pbx_result res = AST_PBX_SUCCESS; - if (increase_call_count(c)) + if (increase_call_count(c)) { return AST_PBX_CALL_LIMIT; + } + + res = __ast_pbx_run(c, args); - res = __ast_pbx_run(c); decrease_call_count(); return res; } +enum ast_pbx_result ast_pbx_run(struct ast_channel *c) +{ + return ast_pbx_run_args(c, NULL); +} + int ast_active_calls(void) { return countcalls; @@ -7776,11 +7786,6 @@ static int pbx_builtin_answer(struct ast_channel *chan, void *data) return __ast_answer(chan, delay); } -static int pbx_builtin_keepalive(struct ast_channel *chan, void *data) -{ - return AST_PBX_KEEPALIVE; -} - static int pbx_builtin_incomplete(struct ast_channel *chan, void *data) { char *options = data;