From: Kristian F. Høgh Date: Wed, 13 Jun 2018 07:25:12 +0000 (+0200) Subject: app_queue: Add option for predial handlers on caller and callee channels X-Git-Tag: 16.0.0-rc1~82^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=184b375b417f0c2ad2b891372d1ab46f70ce86e8;p=thirdparty%2Fasterisk.git app_queue: Add option for predial handlers on caller and callee channels Add predial handler support to app_queue. app_dial (ASTERISK_19548) and app_originate (ASTERISK_26587) have the ability to execute predial handlers on caller and callee channels. This patch adds predial handlers to app_queue and uses the same options as Dial and Originate (b and B). The caller routine gets executed when the caller first enters the queue. The callee routine gets executed for each queue member when they are about to be called. ASTERISK-27912 Change-Id: I5acf5c32587ee008658d12e8a8049eb8fa4d0f24 --- diff --git a/CHANGES b/CHANGES index e969d85bf4..5cfad794c9 100644 --- a/CHANGES +++ b/CHANGES @@ -67,6 +67,10 @@ app_queue When set the wrapuptime on the member is used instead of the wrapuptime defined for the queue itself. + * Added predial handler support for caller and callee channels with the + B and b options respectively. This is similar to the predial support + in app_dial. + res_config_sqlite ------------------ * The res_config_sqlite module is now deprecated, users should migrate to the diff --git a/apps/app_queue.c b/apps/app_queue.c index 3047648de4..052d528b8b 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -133,6 +133,27 @@ + + @@ -1325,15 +1346,21 @@ enum { OPT_CALLER_AUTOMIXMON = (1 << 16), OPT_CALLEE_AUTOMON = (1 << 17), OPT_CALLER_AUTOMON = (1 << 18), + OPT_PREDIAL_CALLEE = (1 << 19), + OPT_PREDIAL_CALLER = (1 << 20), }; enum { OPT_ARG_CALLEE_GO_ON = 0, + OPT_ARG_PREDIAL_CALLEE, + OPT_ARG_PREDIAL_CALLER, /* note: this entry _MUST_ be the last one in the enum */ OPT_ARG_ARRAY_SIZE }; AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS + AST_APP_OPTION_ARG('b', OPT_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE), + AST_APP_OPTION_ARG('B', OPT_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER), AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED), AST_APP_OPTION('c', OPT_GO_ON), AST_APP_OPTION('d', OPT_DATA_QUALITY), @@ -1545,6 +1572,7 @@ struct queue_ent { char announce[PATH_MAX]; /*!< Announcement to play for member when call is answered */ char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */ char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */ + const char *predial_callee; /*!< Gosub app arguments for outgoing calls. NULL if not supplied. */ int valid_digits; /*!< Digits entered correspond to valid extension. Exited */ int pos; /*!< Where we are in the queue */ int prio; /*!< Our priority */ @@ -4559,6 +4587,11 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies ast_channel_unlock(tmp->chan); ast_channel_unlock(qe->chan); + /* PREDIAL: Run gosub on the callee's channel */ + if (qe->predial_callee) { + ast_pre_call(tmp->chan, qe->predial_callee); + } + /* Place the call, but don't wait on the answer */ if ((res = ast_call(tmp->chan, location, 0))) { /* Again, keep going even if there's an error */ @@ -4615,6 +4648,16 @@ static struct callattempt *find_best(struct callattempt *outgoing) static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies) { int ret = 0; + struct callattempt *cur; + + if (qe->predial_callee) { + ast_autoservice_start(qe->chan); + for (cur = outgoing; cur; cur = cur->q_next) { + if (cur->stillgoing && cur->chan) { + ast_autoservice_start(cur->chan); + } + } + } while (ret == 0) { struct callattempt *best = find_best(outgoing); @@ -4623,18 +4666,23 @@ static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *bus break; } if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) { - struct callattempt *cur; /* Ring everyone who shares this best metric (for ringall) */ for (cur = outgoing; cur; cur = cur->q_next) { if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) { ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric); ret |= ring_entry(qe, cur, busies); + if (qe->predial_callee && cur->chan) { + ast_autoservice_start(cur->chan); + } } } } else { /* Ring just the best channel */ ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric); ret = ring_entry(qe, best, busies); + if (qe->predial_callee && cur->chan) { + ast_autoservice_start(best->chan); + } } /* If we have timed out, break out */ @@ -4644,6 +4692,14 @@ static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *bus break; } } + if (qe->predial_callee) { + for (cur = outgoing; cur; cur = cur->q_next) { + if (cur->stillgoing && cur->chan) { + ast_autoservice_stop(cur->chan); + } + } + ast_autoservice_stop(qe->chan); + } return ret; } @@ -8270,6 +8326,21 @@ static int queue_exec(struct ast_channel *chan, const char *data) S_OR(args.url, ""), S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""), qe.opos); + + /* PREDIAL: Preprocess any callee gosub arguments. */ + if (ast_test_flag(&opts, OPT_PREDIAL_CALLEE) + && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLEE])) { + ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLEE]); + qe.predial_callee = opt_args[OPT_ARG_PREDIAL_CALLEE]; + } + + /* PREDIAL: Run gosub on the caller's channel */ + if (ast_test_flag(&opts, OPT_PREDIAL_CALLER) + && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLER])) { + ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLER]); + ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0); + } + copy_rules(&qe, args.rule); qe.pr = AST_LIST_FIRST(&qe.qe_rules); check_turns: