move a large block into a separate function.
authorLuigi Rizzo <rizzo@icir.org>
Sat, 4 Nov 2006 00:01:40 +0000 (00:01 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Sat, 4 Nov 2006 00:01:40 +0000 (00:01 +0000)
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

apps/app_dial.c

index 5e68156..14a9476 100644 (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);