Make FollowMe optionally update connected line information when the accepting endpoint is bridged.

Like Dial and Queue, FollowMe needs to deal with
AST_CONTROL_CONNECTED_LINE information so when the parties are initially
bridged, the connected line information will be correct.

* Added the 'I' option just like the app_dial and app_queue 'I' option.

* Made 'N' option ignored if the call is already answered.

(closes issue ASTERISK-18969)
Reported by: rmudgett
Tested by: rmudgett

Review: https://reviewboard.asterisk.org/r/1656/
........

Merged revisions 350364 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 350415 from http://svn.asterisk.org/svn/asterisk/branches/10


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@350416 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/11.2
Richard Mudgett 13 years ago
parent 9748f19e96
commit edf466012f

@ -95,6 +95,14 @@ Dialplan functions
The MAILBOX_EXISTS dialplan function has been deprecated in favour of The MAILBOX_EXISTS dialplan function has been deprecated in favour of
VM_INFO. VM_INFO.
Followme changes
-------------
* A new option, 'I' has been added to app_followme.
By setting this option, Asterisk will not update the caller with
connected line changes when they occur. This is similar to app_dial
and app_queue.
* The 'N' option is now ignored if the call is already answered.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
--- Functionality changes from Asterisk 1.8 to Asterisk 10 ------------------- --- Functionality changes from Asterisk 1.8 to Asterisk 10 -------------------
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

@ -203,8 +203,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>Asterisk will ignore any forwarding requests it may receive on this dial attempt.</para> <para>Asterisk will ignore any forwarding requests it may receive on this dial attempt.</para>
</option> </option>
<option name="I"> <option name="I">
<para>Asterisk will ignore any connected line update requests or redirecting party update <para>Asterisk will ignore any connected line update requests or any redirecting party
requests it may receiveon this dial attempt.</para> update requests it may receive on this dial attempt.</para>
</option> </option>
<option name="k"> <option name="k">
<para>Allow the called party to enable parking of the call by sending <para>Allow the called party to enable parking of the call by sending

@ -67,31 +67,41 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<parameter name="followmeid" required="true" /> <parameter name="followmeid" required="true" />
<parameter name="options"> <parameter name="options">
<optionlist> <optionlist>
<option name="s">
<para>Playback the incoming status message prior to starting
the follow-me step(s)</para>
</option>
<option name="a"> <option name="a">
<para>Record the caller's name so it can be announced to the <para>Record the caller's name so it can be announced to the
callee on each step.</para> callee on each step.</para>
</option> </option>
<option name="n">
<para>Playback the unreachable status message if we've run out
of steps to reach the or the callee has elected not to be reachable.</para>
</option>
<option name="N">
<para>Don't answer the incoming call until we're ready to
connect the caller or give up. This will disable all the other
options while implicitly turning on the 'd' option.</para>
</option>
<option name="d"> <option name="d">
<para>Disable the 'Please hold while we try to connect your call' announcement.</para> <para>Disable the 'Please hold while we try to connect your call' announcement.</para>
</option> </option>
<option name="I">
<para>Asterisk will ignore any connected line update requests
it may receive on this dial attempt.</para>
</option>
<option name="l"> <option name="l">
<para>Disable local call optimization so that applications with <para>Disable local call optimization so that applications with
audio hooks between the local bridge don't get dropped when the audio hooks between the local bridge don't get dropped when the
calls get joined directly.</para> calls get joined directly.</para>
</option> </option>
<option name="N">
<para>Don't answer the incoming call until we're ready to
connect the caller or give up.</para>
<note>
<para>This option is ignored if the call is already answered.</para>
</note>
<note>
<para>If the call is not already answered, the 'a' and 's'
options are ignored while the 'd' option is implicitly enabled.</para>
</note>
</option>
<option name="n">
<para>Playback the unreachable status message if we've run out
of steps or the callee has elected not to be reachable.</para>
</option>
<option name="s">
<para>Playback the incoming status message prior to starting
the follow-me step(s)</para>
</option>
</optionlist> </optionlist>
</parameter> </parameter>
</syntax> </syntax>
@ -140,13 +150,23 @@ struct call_followme {
}; };
struct fm_args { struct fm_args {
/*! Inbound (caller) channel */
struct ast_channel *chan; struct ast_channel *chan;
char *mohclass; char *mohclass;
AST_LIST_HEAD_NOLOCK(cnumbers, number) cnumbers; AST_LIST_HEAD_NOLOCK(cnumbers, number) cnumbers;
/*! Winning outbound (callee) channel */
struct ast_channel *outbound;
/*! Accumulated connected line information from inbound call. */
struct ast_party_connected_line connected_in;
/*! Accumulated connected line information from outbound call. */
struct ast_party_connected_line connected_out;
/*! TRUE if connected line information from inbound call changed. */
int pending_in_connected_update:1;
/*! TRUE if connected line information from outbound call is available. */
int pending_out_connected_update:1;
int status; int status;
char context[AST_MAX_CONTEXT]; char context[AST_MAX_CONTEXT];
char namerecloc[AST_MAX_CONTEXT]; char namerecloc[AST_MAX_CONTEXT];
struct ast_channel *outbound;
char takecall[20]; /*!< Digit mapping to take a call */ char takecall[20]; /*!< Digit mapping to take a call */
char nextindp[20]; /*!< Digit mapping to decline a call */ char nextindp[20]; /*!< Digit mapping to decline a call */
char callfromprompt[PATH_MAX]; /*!< Sound prompt name and path */ char callfromprompt[PATH_MAX]; /*!< Sound prompt name and path */
@ -160,12 +180,17 @@ struct fm_args {
struct findme_user { struct findme_user {
struct ast_channel *ochan; struct ast_channel *ochan;
/*! Accumulated connected line information from outgoing call. */
struct ast_party_connected_line connected;
long digts;
int ynidx;
int state; int state;
char dialarg[256]; char dialarg[256];
char yn[10]; char yn[10];
int ynidx; /*! TRUE if call cleared. */
long digts; int cleared:1;
int cleared; /*! TRUE if connected line information is available. */
int pending_connected_update:1;
AST_LIST_ENTRY(findme_user) entry; AST_LIST_ENTRY(findme_user) entry;
}; };
@ -176,15 +201,17 @@ enum {
FOLLOWMEFLAG_DISABLEHOLDPROMPT = (1 << 3), FOLLOWMEFLAG_DISABLEHOLDPROMPT = (1 << 3),
FOLLOWMEFLAG_NOANSWER = (1 << 4), FOLLOWMEFLAG_NOANSWER = (1 << 4),
FOLLOWMEFLAG_DISABLEOPTIMIZATION = (1 << 5), FOLLOWMEFLAG_DISABLEOPTIMIZATION = (1 << 5),
FOLLOWMEFLAG_IGNORE_CONNECTEDLINE = (1 << 6),
}; };
AST_APP_OPTIONS(followme_opts, { AST_APP_OPTIONS(followme_opts, {
AST_APP_OPTION('s', FOLLOWMEFLAG_STATUSMSG ), AST_APP_OPTION('a', FOLLOWMEFLAG_RECORDNAME),
AST_APP_OPTION('a', FOLLOWMEFLAG_RECORDNAME ), AST_APP_OPTION('d', FOLLOWMEFLAG_DISABLEHOLDPROMPT),
AST_APP_OPTION('n', FOLLOWMEFLAG_UNREACHABLEMSG ), AST_APP_OPTION('I', FOLLOWMEFLAG_IGNORE_CONNECTEDLINE),
AST_APP_OPTION('d', FOLLOWMEFLAG_DISABLEHOLDPROMPT ), AST_APP_OPTION('l', FOLLOWMEFLAG_DISABLEOPTIMIZATION),
AST_APP_OPTION('N', FOLLOWMEFLAG_NOANSWER ), AST_APP_OPTION('N', FOLLOWMEFLAG_NOANSWER),
AST_APP_OPTION('l', FOLLOWMEFLAG_DISABLEOPTIMIZATION ), AST_APP_OPTION('n', FOLLOWMEFLAG_UNREACHABLEMSG),
AST_APP_OPTION('s', FOLLOWMEFLAG_STATUSMSG),
}); });
static int ynlongest = 0; static int ynlongest = 0;
@ -538,13 +565,15 @@ static void destroy_calling_tree(struct findme_user_listptr *findme_user_list)
if (!fmuser->cleared) { if (!fmuser->cleared) {
clear_caller(fmuser); clear_caller(fmuser);
} }
ast_party_connected_line_free(&fmuser->connected);
ast_free(fmuser); ast_free(fmuser);
} }
ast_free(findme_user_list); ast_free(findme_user_list);
} }
static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_user_list, struct number *nm, struct ast_channel *caller, char *namerecloc, int *status, struct fm_args *tpargs) static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_user_list, struct number *nm, struct ast_channel *caller, char *namerecloc, struct fm_args *tpargs)
{ {
struct ast_party_connected_line connected;
struct ast_channel *watchers[256]; struct ast_channel *watchers[256];
int pos; int pos;
struct ast_channel *winner; struct ast_channel *winner;
@ -670,12 +699,21 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
} }
if (winner) { if (winner) {
/* Need to find out which channel this is */ /* Need to find out which channel this is */
dg = 0; for (dg = 0; dg < ARRAY_LEN(watchers); ++dg) {
while ((winner != watchers[dg]) && (dg < 256)) if (winner == watchers[dg]) {
dg++; break;
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) }
if (tmpuser->ochan == winner) }
if (dg) {
/* The winner is an outgoing channel. */
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
if (tmpuser->ochan == winner) {
break; break;
}
}
} else {
tmpuser = NULL;
}
f = ast_read(winner); f = ast_read(winner);
if (f) { if (f) {
if (f->frametype == AST_FRAME_CONTROL) { if (f->frametype == AST_FRAME_CONTROL) {
@ -729,32 +767,73 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
ast_verb(3, "%s is ringing\n", ast_channel_name(winner)); ast_verb(3, "%s is ringing\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_PROGRESS: case AST_CONTROL_PROGRESS:
ast_verb(3, "%s is making progress passing it to %s\n", ast_channel_name(winner), ast_channel_name(caller)); ast_verb(3, "%s is making progress\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_VIDUPDATE: case AST_CONTROL_VIDUPDATE:
ast_verb(3, "%s requested a video update, passing it to %s\n", ast_channel_name(winner), ast_channel_name(caller)); ast_verb(3, "%s requested a video update\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_SRCUPDATE: case AST_CONTROL_SRCUPDATE:
ast_verb(3, "%s requested a source update, passing it to %s\n", ast_channel_name(winner), ast_channel_name(caller)); ast_verb(3, "%s requested a source update\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_PROCEEDING: case AST_CONTROL_PROCEEDING:
ast_verb(3, "%s is proceeding passing it to %s\n", ast_channel_name(winner),ast_channel_name(caller)); ast_verb(3, "%s is proceeding\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_HOLD: case AST_CONTROL_HOLD:
ast_verb(3, "Call on %s placed on hold\n", ast_channel_name(winner)); ast_verb(3, "%s placed call on hold\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_UNHOLD: case AST_CONTROL_UNHOLD:
ast_verb(3, "Call on %s left from hold\n", ast_channel_name(winner)); ast_verb(3, "%s removed call from hold\n", ast_channel_name(winner));
break; break;
case AST_CONTROL_OFFHOOK: case AST_CONTROL_OFFHOOK:
case AST_CONTROL_FLASH: case AST_CONTROL_FLASH:
/* Ignore going off hook and flash */ /* Ignore going off hook and flash */
break; break;
case AST_CONTROL_CONNECTED_LINE:
if (!tmpuser) {
/*
* Hold connected line update from caller until we have a
* winner.
*/
ast_verb(3,
"%s connected line has changed. Saving it until we have a winner.\n",
ast_channel_name(winner));
ast_party_connected_line_set_init(&connected, &tpargs->connected_in);
if (!ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected)) {
ast_party_connected_line_set(&tpargs->connected_in,
&connected, NULL);
tpargs->pending_in_connected_update = 1;
}
ast_party_connected_line_free(&connected);
break;
}
if (ast_test_flag(&tpargs->followmeflags, FOLLOWMEFLAG_IGNORE_CONNECTEDLINE)) {
ast_verb(3, "Connected line update from %s prevented.\n",
ast_channel_name(winner));
} else {
ast_verb(3,
"%s connected line has changed. Saving it until answer.\n",
ast_channel_name(winner));
ast_party_connected_line_set_init(&connected, &tmpuser->connected);
if (!ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected)) {
ast_party_connected_line_set(&tmpuser->connected,
&connected, NULL);
tmpuser->pending_connected_update = 1;
}
ast_party_connected_line_free(&connected);
}
break;
case AST_CONTROL_REDIRECTING:
/*
* Ignore because we are masking the FollowMe search progress to
* the caller.
*/
break;
case -1: case -1:
ast_verb(3, "%s stopped sounds\n", ast_channel_name(winner)); ast_verb(3, "%s stopped sounds\n", ast_channel_name(winner));
break; break;
default: default:
ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer); ast_debug(1, "Dunno what to do with control type %d from %s\n",
f->subclass.integer, ast_channel_name(winner));
break; break;
} }
} }
@ -775,25 +854,25 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
} }
if (!strcmp(tmpuser->yn, tpargs->nextindp)) { if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
ast_debug(1, "Next in dial plan step requested.\n"); ast_debug(1, "Next in dial plan step requested.\n");
*status = 1;
ast_frfree(f); ast_frfree(f);
return NULL; return NULL;
} }
} }
} }
ast_frfree(f); ast_frfree(f);
} else { } else {
if (winner) { ast_debug(1, "we didn't get a frame. hanging up. dg is %d\n", dg);
ast_debug(1, "we didn't get a frame. hanging up. dg is %d\n",dg);
if (!dg) { if (!dg) {
/* Caller hung up. */
clear_calling_tree(findme_user_list); clear_calling_tree(findme_user_list);
return NULL; return NULL;
} else { } else {
/* Outgoing channel hung up. */
tmpuser->state = -1; tmpuser->state = -1;
tmpuser->ochan = NULL;
ast_hangup(winner); ast_hangup(winner);
livechannels--; --livechannels;
ast_debug(1, "live channels left %d\n", livechannels); ast_debug(1, "live channels left %d\n", livechannels);
if (!livechannels) { if (!livechannels) {
ast_verb(3, "no live channels left. exiting.\n"); ast_verb(3, "no live channels left. exiting.\n");
@ -801,11 +880,10 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
} }
} }
} }
} } else {
} else
ast_debug(1, "timed out waiting for action\n"); ast_debug(1, "timed out waiting for action\n");
} }
}
/* --- WAIT FOR WINNER NUMBER END! -----------*/ /* --- WAIT FOR WINNER NUMBER END! -----------*/
return NULL; return NULL;
@ -824,7 +902,6 @@ static void findmeexec(struct fm_args *tpargs)
struct findme_user *tmpuser; struct findme_user *tmpuser;
struct findme_user *fmuser; struct findme_user *fmuser;
struct findme_user_listptr *findme_user_list; struct findme_user_listptr *findme_user_list;
int status;
findme_user_list = ast_calloc(1, sizeof(*findme_user_list)); findme_user_list = ast_calloc(1, sizeof(*findme_user_list));
AST_LIST_HEAD_INIT_NOLOCK(findme_user_list); AST_LIST_HEAD_INIT_NOLOCK(findme_user_list);
@ -839,7 +916,7 @@ static void findmeexec(struct fm_args *tpargs)
} }
caller = tpargs->chan; caller = tpargs->chan;
for (idx = 1; !winner && !ast_check_hangup(caller); ++idx) { for (idx = 1; !ast_check_hangup(caller); ++idx) {
/* Find next followme numbers to dial. */ /* Find next followme numbers to dial. */
AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) { AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) {
if (nm->order == idx) { if (nm->order == idx) {
@ -930,17 +1007,30 @@ static void findmeexec(struct fm_args *tpargs)
continue; continue;
} }
status = 0; winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, tpargs);
winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs); if (!winner) {
continue;
}
/* Clean up all calls but winner. */ /* Destroy losing calls up to the winner. The rest will be destroyed later. */
while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) { while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
if (!fmuser->cleared && fmuser->ochan != winner) { if (fmuser->ochan == winner) {
/* Pass any connected line info up. */
tpargs->connected_out = fmuser->connected;
tpargs->pending_out_connected_update = fmuser->pending_connected_update;
ast_free(fmuser);
break;
} else {
/* Destroy losing call. */
if (!fmuser->cleared) {
clear_caller(fmuser); clear_caller(fmuser);
} }
ast_party_connected_line_free(&fmuser->connected);
ast_free(fmuser); ast_free(fmuser);
} }
} }
break;
}
destroy_calling_tree(findme_user_list); destroy_calling_tree(findme_user_list);
if (!winner) { if (!winner) {
tpargs->status = 1; tpargs->status = 1;
@ -1066,7 +1156,6 @@ static int app_exec(struct ast_channel *chan, const char *data)
int res = 0; int res = 0;
char *argstr; char *argstr;
char namerecloc[255]; char namerecloc[255];
int duration = 0;
struct ast_channel *caller; struct ast_channel *caller;
struct ast_channel *outbound; struct ast_channel *outbound;
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
@ -1133,27 +1222,36 @@ static int app_exec(struct ast_channel *chan, const char *data)
} }
ast_mutex_unlock(&f->lock); ast_mutex_unlock(&f->lock);
snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid); /* Forget the 'N' option if the call is already up. */
duration = 5; if (chan->_state == AST_STATE_UP) {
ast_clear_flag(&targs.followmeflags, FOLLOWMEFLAG_NOANSWER);
if (!ast_fileexists(namerecloc, NULL, chan->language)) }
ast_copy_string(namerecloc, "", sizeof(namerecloc));
namerecloc[0] = '\0';
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_NOANSWER)) { if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_NOANSWER)) {
if (chan->_state != AST_STATE_UP) {
ast_indicate(chan, AST_CONTROL_RINGING); ast_indicate(chan, AST_CONTROL_RINGING);
}
} else { } else {
/* Answer the call */ /* Answer the call */
if (chan->_state != AST_STATE_UP) if (chan->_state != AST_STATE_UP) {
ast_answer(chan); ast_answer(chan);
}
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG)) if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG))
ast_stream_and_wait(chan, targs.statusprompt, ""); ast_stream_and_wait(chan, targs.statusprompt, "");
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME)) if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME)) {
if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, NULL, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL) < 0) int duration = 5;
snprintf(namerecloc, sizeof(namerecloc), "%s/followme.%s",
ast_config_AST_SPOOL_DIR, chan->uniqueid);
if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration,
NULL, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL) < 0) {
goto outrun; goto outrun;
}
if (!ast_fileexists(namerecloc, NULL, chan->language)) {
namerecloc[0] = '\0';
}
}
if (!ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_DISABLEHOLDPROMPT)) { if (!ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_DISABLEHOLDPROMPT)) {
if (ast_streamfile(chan, targs.plsholdprompt, chan->language)) if (ast_streamfile(chan, targs.plsholdprompt, chan->language))
@ -1167,6 +1265,9 @@ static int app_exec(struct ast_channel *chan, const char *data)
targs.status = 0; targs.status = 0;
targs.chan = chan; targs.chan = chan;
ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc)); ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc));
ast_channel_lock(chan);
ast_connected_line_copy_from_caller(&targs.connected_in, &chan->caller);
ast_channel_unlock(chan);
findmeexec(&targs); findmeexec(&targs);
@ -1176,6 +1277,7 @@ static int app_exec(struct ast_channel *chan, const char *data)
if (!ast_strlen_zero(namerecloc)) if (!ast_strlen_zero(namerecloc))
unlink(namerecloc); unlink(namerecloc);
if (targs.status != 100) {
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_NOANSWER)) { if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_NOANSWER)) {
if (chan->_state != AST_STATE_UP) { if (chan->_state != AST_STATE_UP) {
ast_answer(chan); ast_answer(chan);
@ -1184,7 +1286,6 @@ static int app_exec(struct ast_channel *chan, const char *data)
ast_moh_stop(chan); ast_moh_stop(chan);
} }
if (targs.status != 100) {
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG)) if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG))
ast_stream_and_wait(chan, targs.sorryprompt, ""); ast_stream_and_wait(chan, targs.sorryprompt, "");
res = 0; res = 0;
@ -1201,6 +1302,21 @@ static int app_exec(struct ast_channel *chan, const char *data)
config.end_bridge_callback_data = chan; config.end_bridge_callback_data = chan;
config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
/* Update connected line to caller if available. */
if (targs.pending_out_connected_update) {
if (ast_channel_connected_line_macro(outbound, caller, &targs.connected_out, 1, 0)) {
ast_channel_update_connected_line(caller, &targs.connected_out, NULL);
}
}
if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_NOANSWER)) {
if (caller->_state != AST_STATE_UP) {
ast_answer(caller);
}
} else {
ast_moh_stop(caller);
}
/* Be sure no generators are left on it */ /* Be sure no generators are left on it */
ast_deactivate_generator(caller); ast_deactivate_generator(caller);
/* Make sure channels are compatible */ /* Make sure channels are compatible */
@ -1210,12 +1326,21 @@ static int app_exec(struct ast_channel *chan, const char *data)
ast_hangup(outbound); ast_hangup(outbound);
goto outrun; goto outrun;
} }
/* Update connected line to winner if changed. */
if (targs.pending_in_connected_update) {
if (ast_channel_connected_line_macro(caller, outbound, &targs.connected_in, 0, 0)) {
ast_channel_update_connected_line(outbound, &targs.connected_in, NULL);
}
}
res = ast_bridge_call(caller, outbound, &config); res = ast_bridge_call(caller, outbound, &config);
ast_hangup(outbound); ast_hangup(outbound);
} }
outrun: outrun:
ast_party_connected_line_free(&targs.connected_in);
ast_party_connected_line_free(&targs.connected_out);
if (f->realtime) { if (f->realtime) {
/* Not in list */ /* Not in list */
free_numbers(f); free_numbers(f);

Loading…
Cancel
Save