diff --git a/apps/app_dial.c b/apps/app_dial.c index 72a38ce9cf..ceca20f120 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -2478,7 +2478,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast ast_autoservice_start(chan); ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLEE]); AST_LIST_TRAVERSE(&out_chans, tmp, node) { - ast_app_exec_sub(NULL, tmp->chan, opt_args[OPT_ARG_PREDIAL_CALLEE]); + ast_pre_call(tmp->chan, opt_args[OPT_ARG_PREDIAL_CALLEE]); } ast_autoservice_stop(chan); } diff --git a/channels/chan_local.c b/channels/chan_local.c index a7e83bcfa2..a37a4a4ed8 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -95,6 +95,7 @@ static struct ast_jb_conf g_jb_conf = { static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause); static int local_digit_begin(struct ast_channel *ast, char digit); static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration); +static int local_pre_call(struct ast_channel *ast, const char *sub_args); static int local_call(struct ast_channel *ast, const char *dest, int timeout); static int local_hangup(struct ast_channel *ast); static int local_answer(struct ast_channel *ast); @@ -116,6 +117,7 @@ static struct ast_channel_tech local_tech = { .requester = local_request, .send_digit_begin = local_digit_begin, .send_digit_end = local_digit_end, + .pre_call = local_pre_call, .call = local_call, .hangup = local_hangup, .answer = local_answer, @@ -1257,6 +1259,34 @@ static struct ast_channel *local_request(const char *type, struct ast_format_cap return chan; } +static int local_pre_call(struct ast_channel *ast, const char *sub_args) +{ + struct local_pvt *p = ast_channel_tech_pvt(ast); + struct ast_channel *chan; + int res; + + ao2_lock(p); + chan = p->chan; + if (chan) { + ast_channel_ref(chan); + } + ao2_unlock(p); + if (!chan) { + return -1; + } + + /* + * Execute the predial routine on the ;2 channel so any channel + * variables set by the predial will be available to the local + * channel PBX. + */ + ast_channel_unlock(ast); + res = ast_app_exec_sub(NULL, chan, sub_args); + ast_channel_unref(chan); + ast_channel_lock(ast); + return res; +} + /*! \brief CLI command "local show channels" */ static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index ab6c736ed0..d71b7e5121 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -676,6 +676,20 @@ struct ast_channel_tech { * parameters as a parameter. */ int (* cc_callback)(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback); + + /*! + * \brief Execute a Gosub call on the channel in a technology specific way before a call is placed. + * \since 11.0 + * + * \param chan Channel to execute Gosub in a tech specific way. + * \param sub_args Gosub application parameter string. + * + * \note The chan is locked before calling. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*pre_call)(struct ast_channel *chan, const char *sub_args); }; /*! Kill the channel channel driver technology descriptor. */ @@ -1526,6 +1540,24 @@ int ast_raw_answer(struct ast_channel *chan, int cdr_answer); */ int __ast_answer(struct ast_channel *chan, unsigned int delay, int cdr_answer); +/*! + * \brief Execute a Gosub call on the channel before a call is placed. + * \since 11.0 + * + * \details + * This is called between ast_request() and ast_call() to + * execute a predial routine on the newly created channel. + * + * \param chan Channel to execute Gosub. + * \param sub_args Gosub application parameter string. + * + * \note Absolutely _NO_ channel locks should be held before calling this function. + * + * \retval 0 on success. + * \retval -1 on error. + */ +int ast_pre_call(struct ast_channel *chan, const char *sub_args); + /*! * \brief Make a call * \note Absolutely _NO_ channel locks should be held before calling this function. diff --git a/main/channel.c b/main/channel.c index 3d8e223026..c00ffb5366 100644 --- a/main/channel.c +++ b/main/channel.c @@ -5671,6 +5671,23 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request return NULL; } +int ast_pre_call(struct ast_channel *chan, const char *sub_args) +{ + int (*pre_call)(struct ast_channel *chan, const char *sub_args); + + ast_channel_lock(chan); + pre_call = ast_channel_tech(chan)->pre_call; + if (pre_call) { + int res; + + res = pre_call(chan, sub_args); + ast_channel_unlock(chan); + return res; + } + ast_channel_unlock(chan); + return ast_app_exec_sub(NULL, chan, sub_args); +} + int ast_call(struct ast_channel *chan, const char *addr, int timeout) { /* Place an outgoing call, but don't wait any longer than timeout ms before returning.