summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-04-28 00:31:47 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-04-28 00:31:47 +0000
commite8a6e0ef0e672ebe823500538d2c06e7bad591e0 (patch)
tree203260522fde703c159ce9ebe0e22321a400518f /apps
parentf7c174ff84c636bbaca746243bd05bb63f9ede81 (diff)
PreDial - Ability to run dialplan on callee and caller channels before Dial.
Thanks to Mark Murawski for the initial patch and feature definition. (closes issue ASTERISK-19548) Reported by: Mark Murawski Review: https://reviewboard.asterisk.org/r/1878/ Review: https://reviewboard.asterisk.org/r/1229/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@364436 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps')
-rw-r--r--apps/app_dial.c248
1 files changed, 173 insertions, 75 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 875e943e3..72a38ce9c 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -108,6 +108,27 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
channel before doing anything on the called channel. You will rarely need to use
this option, the default behavior is adequate in most cases.</para>
</option>
+ <option name="b" argsep="^">
+ <para>Before initiating the actual call, Gosub to the specified
+ location using the newly created channel(s). The Gosub will be
+ executed for each destination channel.</para>
+ <argument name="context" required="false" />
+ <argument name="exten" required="false" />
+ <argument name="priority" required="true" hasparams="optional" argsep="^">
+ <argument name="arg1" multiple="true" required="true" />
+ <argument name="argN" />
+ </argument>
+ </option>
+ <option name="B" argsep="^">
+ <para>Before initiating the actual call, Gosub to the specified
+ location using the current channel.</para>
+ <argument name="context" required="false" />
+ <argument name="exten" required="false" />
+ <argument name="priority" required="true" hasparams="optional" argsep="^">
+ <argument name="arg1" multiple="true" required="true" />
+ <argument name="argN" />
+ </argument>
+ </option>
<option name="C">
<para>Reset the call detail record (CDR) for this call.</para>
</option>
@@ -587,6 +608,8 @@ enum {
#define OPT_FORCE_CID_TAG (1LLU << 38)
#define OPT_FORCE_CID_PRES (1LLU << 39)
#define OPT_CALLER_ANSWER (1LLU << 40)
+#define OPT_PREDIAL_CALLEE (1LLU << 41)
+#define OPT_PREDIAL_CALLER (1LLU << 42)
enum {
OPT_ARG_ANNOUNCE = 0,
@@ -606,6 +629,8 @@ enum {
OPT_ARG_FORCECLID,
OPT_ARG_FORCE_CID_TAG,
OPT_ARG_FORCE_CID_PRES,
+ OPT_ARG_PREDIAL_CALLEE,
+ OPT_ARG_PREDIAL_CALLER,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
};
@@ -613,6 +638,8 @@ enum {
AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
AST_APP_OPTION('a', OPT_CALLER_ANSWER),
+ 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_RESETCDR),
AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
AST_APP_OPTION('d', OPT_DTMF_EXIT),
@@ -640,9 +667,9 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
AST_APP_OPTION_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK),
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
AST_APP_OPTION_ARG('s', OPT_FORCE_CID_TAG, OPT_ARG_FORCE_CID_TAG),
- AST_APP_OPTION_ARG('u', OPT_FORCE_CID_PRES, OPT_ARG_FORCE_CID_PRES),
AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
+ AST_APP_OPTION_ARG('u', OPT_FORCE_CID_PRES, OPT_ARG_FORCE_CID_PRES),
AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
AST_APP_OPTION('W', OPT_CALLER_MONITOR),
@@ -662,16 +689,26 @@ END_OPTIONS );
* The list of active channels
*/
struct chanlist {
- struct chanlist *next;
+ AST_LIST_ENTRY(chanlist) node;
struct ast_channel *chan;
+ /*! Channel interface dialing string (is tech/number). (Stored in stuff[]) */
+ const char *interface;
+ /*! Channel technology name. (Stored in stuff[]) */
+ const char *tech;
+ /*! Channel device addressing. (Stored in stuff[]) */
+ const char *number;
uint64_t flags;
/*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
struct ast_party_connected_line connected;
/*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
unsigned int pending_connected_update:1;
struct ast_aoc_decoded *aoc_s_rate_list;
+ /*! The interface, tech, and number strings are stuffed here. */
+ char stuff[0];
};
+AST_LIST_HEAD_NOLOCK(dial_head, chanlist);
+
static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
static void chanlist_free(struct chanlist *outgoing)
@@ -681,11 +718,12 @@ static void chanlist_free(struct chanlist *outgoing)
ast_free(outgoing);
}
-static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
+static void hanguptree(struct dial_head *out_chans, struct ast_channel *exception, int answered_elsewhere)
{
/* Hang up a tree of stuff */
- struct chanlist *oo;
- while (outgoing) {
+ struct chanlist *outgoing;
+
+ while ((outgoing = AST_LIST_REMOVE_HEAD(out_chans, node))) {
/* Hangup any existing lines we have open */
if (outgoing->chan && (outgoing->chan != exception)) {
if (answered_elsewhere) {
@@ -696,9 +734,7 @@ static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception,
}
ast_hangup(outgoing->chan);
}
- oo = outgoing;
- outgoing = outgoing->next;
- chanlist_free(oo);
+ chanlist_free(outgoing);
}
}
@@ -1004,7 +1040,7 @@ struct privacy_args {
};
static struct ast_channel *wait_for_answer(struct ast_channel *in,
- struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
+ struct dial_head *out_chans, int *to, struct ast_flags64 *peerflags,
char *opt_args[],
struct privacy_args *pa,
const struct cause_args *num_in, int *result, char *dtmf_progress,
@@ -1015,13 +1051,14 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
int prestart = num.busy + num.congestion + num.nochan;
int orig = *to;
struct ast_channel *peer = NULL;
- /* single is set if only one destination is enabled */
- int single = outgoing && !outgoing->next;
- int caller_entertained = outgoing
- && ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
#ifdef HAVE_EPOLL
struct chanlist *epollo;
#endif
+ struct chanlist *outgoing = AST_LIST_FIRST(out_chans);
+ /* single is set if only one destination is enabled */
+ int single = outgoing && !AST_LIST_NEXT(outgoing, node);
+ int caller_entertained = outgoing
+ && ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
struct ast_party_connected_line connected_caller;
struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
int cc_recall_core_id;
@@ -1064,8 +1101,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
is_cc_recall = ast_cc_is_recall(in, &cc_recall_core_id, NULL);
#ifdef HAVE_EPOLL
- for (epollo = outgoing; epollo; epollo = epollo->next)
+ AST_LIST_TRAVERSE(out_chans, epollo, node) {
ast_poll_channel_add(in, epollo->chan);
+ }
#endif
while (*to && !peer) {
@@ -1076,7 +1114,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
struct ast_channel *watchers[AST_MAX_WATCHERS];
watchers[pos++] = in;
- for (o = outgoing; o; o = o->next) {
+ AST_LIST_TRAVERSE(out_chans, o, node) {
/* Keep track of important channels */
if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan)
watchers[pos++] = o->chan;
@@ -1101,7 +1139,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
return NULL;
}
winner = ast_waitfor_n(watchers, pos, to);
- for (o = outgoing; o; o = o->next) {
+ AST_LIST_TRAVERSE(out_chans, o, node) {
struct ast_frame *f;
struct ast_channel *c = o->chan;
@@ -1486,7 +1524,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
}
/* Send the frame from the in channel to all outgoing channels. */
- for (o = outgoing; o; o = o->next) {
+ AST_LIST_TRAVERSE(out_chans, o, node) {
if (!o->chan || !ast_test_flag64(o, DIAL_STILLGOING)) {
/* This outgoing channel has died so don't send the frame to it. */
continue;
@@ -1575,7 +1613,7 @@ skip_frame:;
}
#ifdef HAVE_EPOLL
- for (epollo = outgoing; epollo; epollo = epollo->next) {
+ AST_LIST_TRAVERSE(out_chans, epollo, node) {
if (epollo->chan)
ast_poll_channel_del(in, epollo->chan);
}
@@ -1918,12 +1956,13 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
{
int res = -1; /* default: error */
char *rest, *cur; /* scan the list of destinations */
- struct chanlist *outgoing = NULL; /* list of destinations */
+ struct dial_head out_chans = AST_LIST_HEAD_NOLOCK_INIT_VALUE; /* list of destinations */
+ struct chanlist *outgoing;
+ struct chanlist *tmp;
struct ast_channel *peer;
int to; /* timeout */
struct cause_args num = { chan, 0, 0, 0 };
int cause;
- char numsubst[256];
struct ast_bridge_config config = { { 0, } };
struct timeval calldurationlimit = { 0, };
@@ -1983,7 +2022,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
+ ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
return -1;
}
@@ -1999,7 +2038,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
}
if (ast_strlen_zero(args.peers)) {
- ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
+ ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
goto done;
}
@@ -2154,34 +2193,60 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
ast_channel_lock(chan);
if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
- outbound_group = ast_strdupa(outbound_group);
+ outbound_group = ast_strdupa(outbound_group);
pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
} else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) {
outbound_group = ast_strdupa(outbound_group);
}
- ast_channel_unlock(chan);
+ ast_channel_unlock(chan);
ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_IGNORE_CONNECTEDLINE |
OPT_CANCEL_TIMEOUT | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB | OPT_FORCECLID);
+ /* PREDIAL: Run gosub on the caller's channel */
+ if (ast_test_flag64(&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]);
+ }
+
/* loop through the list of dial destinations */
rest = args.peers;
while ((cur = strsep(&rest, "&")) ) {
- struct chanlist *tmp;
struct ast_channel *tc; /* channel for this destination */
- /* Get a technology/[device:]number pair */
+ /* Get a technology/resource pair */
char *number = cur;
- char *interface = ast_strdupa(number);
char *tech = strsep(&number, "/");
+ size_t tech_len;
+ size_t number_len;
/* find if we already dialed this interface */
struct ast_dialed_interface *di;
AST_LIST_HEAD(,ast_dialed_interface) *dialed_interfaces;
+
num_dialed++;
if (ast_strlen_zero(number)) {
- ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
+ ast_log(LOG_WARNING, "Dial argument takes format (technology/resource)\n");
goto out;
}
- if (!(tmp = ast_calloc(1, sizeof(*tmp))))
+
+ tech_len = strlen(tech) + 1;
+ number_len = strlen(number) + 1;
+ tmp = ast_calloc(1, sizeof(*tmp) + (2 * tech_len) + number_len);
+ if (!tmp) {
goto out;
+ }
+
+ /* Save tech, number, and interface. */
+ cur = tmp->stuff;
+ strcpy(cur, tech);
+ tmp->tech = cur;
+ cur += tech_len;
+ strcpy(cur, tech);
+ cur[tech_len - 1] = '/';
+ tmp->interface = cur;
+ cur += tech_len;
+ strcpy(cur, number);
+ tmp->number = cur;
+
if (opts.flags) {
ast_copy_flags64(tmp, &opts,
OPT_CANCEL_ELSEWHERE |
@@ -2193,7 +2258,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML);
}
- ast_copy_string(numsubst, number, sizeof(numsubst));
+
/* Request the peer */
ast_channel_lock(chan);
@@ -2215,7 +2280,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
chanlist_free(tmp);
goto out;
}
-
datastore->inheritance = DATASTORE_INHERIT_FOREVER;
if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
@@ -2234,14 +2298,13 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
AST_LIST_LOCK(dialed_interfaces);
AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
- if (!strcasecmp(di->interface, interface)) {
+ if (!strcasecmp(di->interface, tmp->interface)) {
ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n",
di->interface);
break;
}
}
AST_LIST_UNLOCK(dialed_interfaces);
-
if (di) {
fulldial++;
chanlist_free(tmp);
@@ -2252,45 +2315,47 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
* which "real" interfaces have been dialed. The Local channel will
* inherit this list so that if it ends up dialing a real interface,
* it won't call one that has already been called. */
- if (strcasecmp(tech, "Local")) {
- if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
- AST_LIST_UNLOCK(dialed_interfaces);
+ if (strcasecmp(tmp->tech, "Local")) {
+ if (!(di = ast_calloc(1, sizeof(*di) + strlen(tmp->interface)))) {
chanlist_free(tmp);
goto out;
}
- strcpy(di->interface, interface);
+ strcpy(di->interface, tmp->interface);
AST_LIST_LOCK(dialed_interfaces);
AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
AST_LIST_UNLOCK(dialed_interfaces);
}
- tc = ast_request(tech, ast_channel_nativeformats(chan), chan, numsubst, &cause);
+ tc = ast_request(tmp->tech, ast_channel_nativeformats(chan), chan, tmp->number, &cause);
if (!tc) {
/* If we can't, just go on to the next call */
ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
- tech, cause, ast_cause2str(cause));
+ tmp->tech, cause, ast_cause2str(cause));
handle_cause(cause, &num);
- if (!rest) /* we are on the last destination */
+ if (!rest) {
+ /* we are on the last destination */
ast_channel_hangupcause_set(chan, cause);
- chanlist_free(tmp);
+ }
if (!ignore_cc && (cause == AST_CAUSE_BUSY || cause == AST_CAUSE_CONGESTION)) {
- if (!ast_cc_callback(chan, tech, numsubst, ast_cc_busy_interface)) {
- ast_cc_extension_monitor_add_dialstring(chan, interface, "");
+ if (!ast_cc_callback(chan, tmp->tech, tmp->number, ast_cc_busy_interface)) {
+ ast_cc_extension_monitor_add_dialstring(chan, tmp->interface, "");
}
}
+ chanlist_free(tmp);
continue;
}
ast_channel_get_device_name(tc, device_name, sizeof(device_name));
if (!ignore_cc) {
- ast_cc_extension_monitor_add_dialstring(chan, interface, device_name);
+ ast_cc_extension_monitor_add_dialstring(chan, tmp->interface, device_name);
}
- pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
+ pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", tmp->number);
ast_channel_lock_both(tc, chan);
/* Setup outgoing SDP to match incoming one */
- if (!outgoing && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
+ if (!AST_LIST_FIRST(&out_chans) && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
+ /* We are on the only destination. */
ast_rtp_instance_early_bridge_make_compatible(tc, chan);
}
@@ -2389,44 +2454,74 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
ast_channel_unlock(tc);
ast_channel_unlock(chan);
- res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */
+
+ /* Put channel in the list of outgoing thingies. */
+ tmp->chan = tc;
+ AST_LIST_INSERT_TAIL(&out_chans, tmp, node);
+ }
+
+ /*
+ * PREDIAL: Run gosub on all of the callee channels
+ *
+ * We run the callee predial before ast_call() in case the user
+ * wishes to do something on the newly created channels before
+ * the channel does anything important.
+ *
+ * Inside the target gosub we will be able to do something with
+ * the newly created channel name ie: now the calling channel
+ * can know what channel will be used to call the destination
+ * ex: now we will know that SIP/abc-123 is calling SIP/def-124
+ */
+ if (ast_test_flag64(&opts, OPT_PREDIAL_CALLEE)
+ && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLEE])
+ && !AST_LIST_EMPTY(&out_chans)) {
+ 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_autoservice_stop(chan);
+ }
+
+ /* Start all outgoing calls */
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&out_chans, tmp, node) {
+ res = ast_call(tmp->chan, tmp->number, 0); /* Place the call, but don't wait on the answer */
ast_channel_lock(chan);
/* Save the info in cdr's that we called them */
if (ast_channel_cdr(chan))
- ast_cdr_setdestchan(ast_channel_cdr(chan), ast_channel_name(tc));
+ ast_cdr_setdestchan(ast_channel_cdr(chan), ast_channel_name(tmp->chan));
/* check the results of ast_call */
if (res) {
/* Again, keep going even if there's an error */
ast_debug(1, "ast call on peer returned %d\n", res);
- ast_verb(3, "Couldn't call %s/%s\n", tech, numsubst);
- if (ast_channel_hangupcause(tc)) {
- ast_channel_hangupcause_set(chan, ast_channel_hangupcause(tc));
+ ast_verb(3, "Couldn't call %s\n", tmp->interface);
+ if (ast_channel_hangupcause(tmp->chan)) {
+ ast_channel_hangupcause_set(chan, ast_channel_hangupcause(tmp->chan));
}
ast_channel_unlock(chan);
- ast_cc_call_failed(chan, tc, interface);
- ast_hangup(tc);
- tc = NULL;
+ ast_cc_call_failed(chan, tmp->chan, tmp->interface);
+ ast_hangup(tmp->chan);
+ tmp->chan = NULL;
+ AST_LIST_REMOVE_CURRENT(node);
chanlist_free(tmp);
continue;
- } else {
- senddialevent(chan, tc, numsubst);
- ast_verb(3, "Called %s/%s\n", tech, numsubst);
- ast_channel_unlock(chan);
}
- /* Put them in the list of outgoing thingies... We're ready now.
- XXX If we're forcibly removed, these outgoing calls won't get
- hung up XXX */
+
+ senddialevent(chan, tmp->chan, tmp->number);
+ ast_channel_unlock(chan);
+
+ ast_verb(3, "Called %s\n", tmp->interface);
ast_set_flag64(tmp, DIAL_STILLGOING);
- tmp->chan = tc;
- tmp->next = outgoing;
- outgoing = tmp;
+
/* If this line is up, don't try anybody else */
- if (ast_channel_state(outgoing->chan) == AST_STATE_UP)
+ if (ast_channel_state(tmp->chan) == AST_STATE_UP) {
break;
+ }
}
-
+ AST_LIST_TRAVERSE_SAFE_END;
+
if (ast_strlen_zero(args.timeout)) {
to = -1;
} else {
@@ -2439,6 +2534,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
}
}
+ outgoing = AST_LIST_FIRST(&out_chans);
if (!outgoing) {
strcpy(pa.status, "CHANUNAVAIL");
if (fulldial == num_dialed) {
@@ -2474,7 +2570,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
}
}
- peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result,
+ peer = wait_for_answer(chan, &out_chans, &to, peerflags, opt_args, &pa, &num, &result,
dtmf_progress, ignore_cc, &forced_clid, &stored_clid);
/* The ast_channel_datastore_remove() function could fail here if the
@@ -2508,8 +2604,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with -1 so that it is hung up properly after the
conversation. */
- hanguptree(outgoing, peer, 1);
- outgoing = NULL;
+ hanguptree(&out_chans, peer, 1);
/* If appropriate, log that we have a destination channel and set the answer time */
if (ast_channel_cdr(chan)) {
ast_cdr_setdestchan(ast_channel_cdr(chan), ast_channel_name(peer));
@@ -2519,11 +2614,14 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer));
ast_channel_lock(peer);
- number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
- if (!number)
- number = numsubst;
- pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
+ number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
+ if (ast_strlen_zero(number)) {
+ number = NULL;
+ } else {
+ number = ast_strdupa(number);
+ }
ast_channel_unlock(peer);
+ pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
@@ -2618,7 +2716,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
ast_channel_exten_set(peer, ast_channel_exten(chan));
ast_channel_priority_set(peer, ast_channel_priority(chan) + 2);
ast_pbx_start(peer);
- hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0);
+ hanguptree(&out_chans, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0);
if (continue_exec)
*continue_exec = 1;
res = 0;
@@ -2903,7 +3001,7 @@ out:
}
ast_channel_early_bridge(chan, NULL);
- hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */
+ hanguptree(&out_chans, NULL, 0); /* In this case, there's no answer anywhere */
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
senddialendevent(chan, pa.status);
ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);