From f6e92c35df357a7f107a0f459089427c4d755af6 Mon Sep 17 00:00:00 2001 From: Jonathan Rose Date: Mon, 9 Dec 2013 22:17:14 +0000 Subject: [PATCH] app_page: Add predial handlers for app_page. (closes issue AFS-14) Review: https://reviewboard.asterisk.org/r/3045/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403576 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 10 +++++++- apps/app_page.c | 40 +++++++++++++++++++++++++++++- include/asterisk/dial.h | 1 + main/dial.c | 55 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index ac63077dc7..6112c6a931 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,9 @@ --- Functionality changes from Asterisk 12 to Asterisk 13 -------------------- ------------------------------------------------------------------------------ +Applications +-------------------------- + ConfBridge -------------------------- * CONFBRIDGE dialplan function is now capable of creating/modifying dynamic @@ -42,9 +45,14 @@ Directory USEREXIT user pressed '#' from the selection prompt to exit FAILED directory failed in a way that wasn't accounted for. Dang. +Page +-------------------------- + * Added options 'b' and 'B' to apply predial handlers for outgoing calls + and for the channel executing Page respectively. + PickupChan -------------------------- -* PickupChan now accepts channel uniqueids of channels to pickup. + * PickupChan now accepts channel uniqueids of channels to pickup. Say -------------------------- diff --git a/apps/app_page.c b/apps/app_page.c index 8e7d1d2bda..31e75e445b 100644 --- a/apps/app_page.c +++ b/apps/app_page.c @@ -65,6 +65,27 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + + @@ -118,14 +139,20 @@ enum page_opt_flags { PAGE_IGNORE_FORWARDS = (1 << 4), PAGE_ANNOUNCE = (1 << 5), PAGE_NOCALLERANNOUNCE = (1 << 6), + PAGE_PREDIAL_CALLEE = (1 << 7), + PAGE_PREDIAL_CALLER = (1 << 8), }; enum { OPT_ARG_ANNOUNCE = 0, - OPT_ARG_ARRAY_SIZE = 1, + OPT_ARG_PREDIAL_CALLEE = 1, + OPT_ARG_PREDIAL_CALLER = 2, + OPT_ARG_ARRAY_SIZE = 3, }; AST_APP_OPTIONS(page_opts, { + AST_APP_OPTION_ARG('b', PAGE_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE), + AST_APP_OPTION_ARG('B', PAGE_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER), AST_APP_OPTION('d', PAGE_DUPLEX), AST_APP_OPTION('q', PAGE_QUIET), AST_APP_OPTION('r', PAGE_RECORD), @@ -283,6 +310,12 @@ static int page_exec(struct ast_channel *chan, const char *data) return -1; } + if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLER) + && !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLER])) { + ast_replace_subargument_delimiter(options.opts[OPT_ARG_PREDIAL_CALLER]); + ast_app_exec_sub(NULL, chan, options.opts[OPT_ARG_PREDIAL_CALLER], 0); + } + /* Go through parsing/calling each device */ while ((tech = strsep(&args.devices, "&"))) { int state = 0; @@ -327,6 +360,11 @@ static int page_exec(struct ast_channel *chan, const char *data) /* Set ANSWER_EXEC as global option */ ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, confbridgeopts); + if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLEE) + && !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLEE])) { + ast_dial_option_global_enable(dial, AST_DIAL_OPTION_PREDIAL, options.opts[OPT_ARG_PREDIAL_CALLEE]); + } + if (timeout) { ast_dial_set_global_timeout(dial, timeout * 1000); } diff --git a/include/asterisk/dial.h b/include/asterisk/dial.h index 7aa892f60f..19b1c87538 100644 --- a/include/asterisk/dial.h +++ b/include/asterisk/dial.h @@ -44,6 +44,7 @@ enum ast_dial_option { AST_DIAL_OPTION_ANSWER_EXEC, /*!< Execute application upon answer in async mode */ AST_DIAL_OPTION_MUSIC, /*!< Play music on hold instead of ringing to the calling channel */ AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, /*!< Disable call forwarding on channels */ + AST_DIAL_OPTION_PREDIAL, /*!< Execute a predial subroutine before dialing */ AST_DIAL_OPTION_MAX, /*!< End terminator -- must always remain last */ }; diff --git a/main/dial.c b/main/dial.c index 8cc6f9c894..134386735a 100644 --- a/main/dial.c +++ b/main/dial.c @@ -145,6 +145,22 @@ static int music_disable(void *data) return 0; } +static void *predial_enable(void *data) +{ + return ast_strdup(data); +} + +static int predial_disable(void *data) +{ + if (!data) { + return -1; + } + + ast_free(data); + + return 0; +} + /*! \brief Application execution function for 'ANSWER_EXEC' option */ static void answer_exec_run(struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args) { @@ -186,6 +202,7 @@ static const struct ast_option_types option_types[] = { { AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable }, /*!< Execute application upon answer in async mode */ { AST_DIAL_OPTION_MUSIC, music_enable, music_disable }, /*!< Play music to the caller instead of ringing */ { AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL, NULL }, /*!< Disable call forwarding on channels */ + { AST_DIAL_OPTION_PREDIAL, predial_enable, predial_disable }, /*!< Execute a subroutine on the outbound channels prior to dialing */ { AST_DIAL_OPTION_MAX, NULL, NULL }, /*!< Terminator of list */ }; @@ -259,7 +276,7 @@ int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device) } /*! \brief Helper function that requests all channels */ -static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channel *chan, struct ast_format_cap *cap) +static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channel *chan, struct ast_format_cap *cap, const char *predial_string) { char numsubst[AST_MAX_EXTENSION]; struct ast_format_cap *cap_all_audio = NULL; @@ -316,6 +333,17 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe ast_channel_stage_snapshot_done(channel->owner); + if (!ast_strlen_zero(predial_string)) { + const char *predial_callee = ast_app_expand_sub_args(chan, predial_string); + if (!predial_callee) { + ast_log(LOG_ERROR, "Could not expand subroutine arguments in predial request '%s'\n", predial_string); + } + ast_autoservice_start(chan); + ast_pre_call(channel->owner, predial_callee); + ast_autoservice_stop(chan); + ast_free((char *) predial_callee); + } + return 0; } @@ -323,10 +351,15 @@ int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_ { struct ast_dial_channel *channel; int res = -1; + char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL]; + + if (!ast_strlen_zero(predial_string)) { + ast_replace_subargument_delimiter(predial_string); + } AST_LIST_LOCK(&dial->channels); AST_LIST_TRAVERSE(&dial->channels, channel, list) { - if ((res = begin_dial_prerun(channel, chan, cap))) { + if ((res = begin_dial_prerun(channel, chan, cap, predial_string))) { break; } } @@ -336,13 +369,13 @@ int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_ } /*! \brief Helper function that does the beginning dialing per-appended channel */ -static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async) +static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async, const char *predial_string) { char numsubst[AST_MAX_EXTENSION]; int res = 1; /* If no owner channel exists yet execute pre-run */ - if (!channel->owner && begin_dial_prerun(channel, chan, NULL)) { + if (!channel->owner && begin_dial_prerun(channel, chan, NULL, predial_string)) { return 0; } @@ -371,11 +404,16 @@ static int begin_dial(struct ast_dial *dial, struct ast_channel *chan, int async { struct ast_dial_channel *channel = NULL; int success = 0; + char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL]; + + if (!ast_strlen_zero(predial_string)) { + ast_replace_subargument_delimiter(predial_string); + } /* Iterate through channel list, requesting and calling each one */ AST_LIST_LOCK(&dial->channels); AST_LIST_TRAVERSE(&dial->channels, channel, list) { - success += begin_dial_channel(channel, chan, async); + success += begin_dial_channel(channel, chan, async, predial_string); } AST_LIST_UNLOCK(&dial->channels); @@ -389,6 +427,11 @@ static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *c struct ast_channel *original = channel->owner; char *tmp = ast_strdupa(ast_channel_call_forward(channel->owner)); char *tech = "Local", *device = tmp, *stuff; + char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL]; + + if (!ast_strlen_zero(predial_string)) { + ast_replace_subargument_delimiter(predial_string); + } /* If call forwarding is disabled just drop the original channel and don't attempt to dial the new one */ if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) { @@ -428,7 +471,7 @@ static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *c channel->owner = NULL; /* Finally give it a go... send it out into the world */ - begin_dial_channel(channel, chan, chan ? 0 : 1); + begin_dial_channel(channel, chan, chan ? 0 : 1, predial_string); return 0; }