move a large block into a separate function.

Mark with XXX a possible bug in previous code which used
the wrong source in case of a forwarded call.

the function do_forward() needs to be split further, as the initial
part is replicated in another places (with some minor differences, most likely
forgotten when updating after the copy).



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47179 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Luigi Rizzo 2006-11-04 00:01:40 +00:00
parent 65beb9dc10
commit 1385b6f047
1 changed files with 93 additions and 83 deletions

View File

@ -419,6 +419,97 @@ static void senddialendevent(const struct ast_channel *src, const char *dialstat
src->name, dialstatus);
}
/* helper function for wait_for_answer() */
static void do_forward(struct dial_localuser *o,
struct cause_args *num, struct ast_flags *peerflags, int single)
{
char tmpchan[256];
struct ast_channel *c = o->chan; /* the winner */
struct ast_channel *in = num->chan; /* the input channel */
char *stuff;
char *tech;
int cause;
ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
if ((stuff = strchr(tmpchan, '/'))) {
*stuff++ = '\0';
tech = tmpchan;
} else {
const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
stuff = tmpchan;
tech = "Local";
}
/* Before processing channel, go ahead and check for forwarding */
o->forwards++;
if (o->forwards < AST_MAX_FORWARDS) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
c = o->chan = NULL;
cause = AST_CAUSE_BUSY;
} else {
/* Setup parameters */
c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
if (!c)
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
else
ast_channel_inherit_variables(in, o->chan);
}
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
cause = AST_CAUSE_CONGESTION;
c = o->chan = NULL;
}
if (!c) {
ast_clear_flag(o, DIAL_STILLGOING);
handle_cause(cause, num);
} else {
char *new_cid_num, *new_cid_name;
struct ast_channel *src;
ast_rtp_make_compatible(c, in, single);
if (ast_test_flag(o, OPT_FORCECLID)) {
new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
new_cid_name = NULL; /* XXX no name ? */
src = c; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
} else {
new_cid_num = ast_strdup(in->cid.cid_num);
new_cid_name = ast_strdup(in->cid.cid_name);
src = in;
}
ast_string_field_set(c, accountcode, src->accountcode);
c->cdrflags = src->cdrflags;
S_REPLACE(c->cid.cid_num, new_cid_num);
S_REPLACE(c->cid.cid_name, new_cid_name);
if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
}
S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
if (ast_call(c, tmpchan, 0)) {
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
ast_clear_flag(o, DIAL_STILLGOING);
ast_hangup(c);
c = o->chan = NULL;
num->nochan++;
} else {
senddialevent(in, c);
/* After calling, set callerid to extension */
if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
char cidname[AST_MAX_EXTENSION];
ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
}
}
}
/* Hangup the original channel now, in case we needed it */
ast_hangup(c);
}
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize,
const struct cause_args *num_in, int priority_jump, int *result)
{
@ -495,90 +586,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
}
if (c != winner)
continue;
/* here, o->chan == c == winner */
if (!ast_strlen_zero(c->call_forward)) {
char tmpchan[256];
char *stuff;
char *tech;
int cause;
ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
if ((stuff = strchr(tmpchan, '/'))) {
*stuff++ = '\0';
tech = tmpchan;
} else {
const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
stuff = tmpchan;
tech = "Local";
}
/* Before processing channel, go ahead and check for forwarding */
o->forwards++;
if (o->forwards < AST_MAX_FORWARDS) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
c = o->chan = NULL;
cause = AST_CAUSE_BUSY;
} else {
/* Setup parameters */
c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
if (!c)
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
else
ast_channel_inherit_variables(in, o->chan);
}
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
cause = AST_CAUSE_CONGESTION;
c = o->chan = NULL;
}
if (!c) {
ast_clear_flag(o, DIAL_STILLGOING);
handle_cause(cause, &num);
} else {
char *new_cid_num, *new_cid_name;
struct ast_channel *src;
ast_rtp_make_compatible(c, in, single);
if (ast_test_flag(o, OPT_FORCECLID)) {
new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
new_cid_name = NULL; /* XXX no name ? */
src = winner;
} else {
new_cid_num = ast_strdup(in->cid.cid_num);
new_cid_name = ast_strdup(in->cid.cid_name);
src = in;
}
ast_string_field_set(c, accountcode, src->accountcode);
c->cdrflags = src->cdrflags;
S_REPLACE(c->cid.cid_num, new_cid_num);
S_REPLACE(c->cid.cid_name, new_cid_name);
if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
}
S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
if (ast_call(c, tmpchan, 0)) {
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
ast_clear_flag(o, DIAL_STILLGOING);
ast_hangup(c);
c = o->chan = NULL;
num.nochan++;
} else {
senddialevent(in, c);
/* After calling, set callerid to extension */
if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
char cidname[AST_MAX_EXTENSION];
ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
}
}
}
/* Hangup the original channel now, in case we needed it */
ast_hangup(winner);
do_forward(o, &num, peerflags, single);
continue;
}
f = ast_read(winner);