Repair IAXVAR implementation so that it works again (regression?)
authorTilghman Lesher <tilghman@meg.abyt.es>
Sat, 13 Sep 2008 13:54:15 +0000 (13:54 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Sat, 13 Sep 2008 13:54:15 +0000 (13:54 +0000)
(closes issue #13354)
 Reported by: adomjan
 Patches:
       20080828__bug13354.diff.txt uploaded by Corydon76 (license 14)
       20080829__bug13354__1.6.0.diff.txt uploaded by Corydon76 (license 14)
 Tested by: Corydon76, adomjan

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@143031 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
channels/chan_iax2.c
channels/iax2-parser.c

index 9199635..6a1022a 100644 (file)
@@ -1492,6 +1492,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                
                /* Inherit specially named variables from parent channel */
                ast_channel_inherit_variables(chan, tc);
+               ast_channel_datastore_inherit(chan, tc);
 
                tc->appl = "AppDial";
                tc->data = "(Outgoing Line)";
index 32ebe34..01f5ba6 100644 (file)
@@ -655,7 +655,10 @@ struct chan_iax2_pvt {
        int calling_pres;
        int amaflags;
        AST_LIST_HEAD_NOLOCK(, iax2_dpcache) dpentries;
+       /*! variables inherited from the user definition */
        struct ast_variable *vars;
+       /*! variables transmitted in a NEW packet */
+       struct ast_variable *iaxvars;
        /*! last received remote rr */
        struct iax_rr remote_rr;
        /*! Current base time: (just for stats) */
@@ -3749,10 +3752,12 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
        /* Add remote vars */
        if (variablestore) {
                AST_LIST_HEAD(, ast_var_t) *variablelist = variablestore->data;
+               ast_debug(1, "Found an IAX variable store on this channel\n");
                AST_LIST_LOCK(variablelist);
                AST_LIST_TRAVERSE(variablelist, var, entries) {
                        char tmp[256];
                        int i;
+                       ast_debug(1, "Found IAXVAR '%s' with value '%s' (to transmit)\n", ast_var_name(var), ast_var_value(var));
                        /* Automatically divide the value up into sized chunks */
                        for (i = 0; i < strlen(ast_var_value(var)); i += 255 - (strlen(ast_var_name(var)) + 1)) {
                                snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var), ast_var_value(var) + i);
@@ -4258,6 +4263,42 @@ static struct ast_channel *ast_iax2_new(int callno, int state, int capability)
                for (v = i->vars ; v ; v = v->next)
                        pbx_builtin_setvar_helper(tmp, v->name, v->value);
        }
+       if (i->iaxvars) {
+               struct ast_datastore *variablestore;
+               struct ast_variable *var, *prev = NULL;
+               AST_LIST_HEAD(, ast_var_t) *varlist;
+               ast_debug(1, "Loading up the channel with IAXVARs\n");
+               varlist = ast_calloc(1, sizeof(*varlist));
+               variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL);
+               if (variablestore && varlist) {
+                       variablestore->data = varlist;
+                       variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
+                       AST_LIST_HEAD_INIT(varlist);
+                       for (var = i->iaxvars; var; var = var->next) {
+                               struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
+                               if (prev)
+                                       ast_free(prev);
+                               prev = var;
+                               if (!newvar) {
+                                       /* Don't abort list traversal, as this would leave i->iaxvars in an inconsistent state. */
+                                       ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
+                               } else {
+                                       AST_LIST_INSERT_TAIL(varlist, newvar, entries);
+                               }
+                       }
+                       if (prev)
+                               ast_free(prev);
+                       i->iaxvars = NULL;
+                       ast_channel_datastore_add(i->owner, variablestore);
+               } else {
+                       if (variablestore) {
+                               ast_datastore_free(variablestore);
+                       }
+                       if (varlist) {
+                               ast_free(varlist);
+                       }
+               }
+       }
 
        if (state != AST_STATE_DOWN) {
                if (ast_pbx_start(tmp)) {
@@ -8344,8 +8385,10 @@ static int socket_process(struct iax2_thread *thread)
                                }
                                f.data.ptr = NULL;
                                f.datalen = 0;
-                       } else
+                       } else {
                                f.data.ptr = thread->buf + sizeof(*fh);
+                               memset(&ies, 0, sizeof(ies));
+                       }
                } else {
                        if (f.frametype == AST_FRAME_IAX)
                                f.data.ptr = NULL;
@@ -8365,20 +8408,27 @@ static int socket_process(struct iax2_thread *thread)
                                if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
                                        ast_mutex_unlock(&iaxsl[fr->callno]);
                                        return 1;
-                               } else if (ies.vars) {
-                                       struct ast_datastore *variablestore;
-                                       struct ast_variable *var, *prev = NULL;
-                                       AST_LIST_HEAD(, ast_var_t) *varlist;
+                               }
+                       }
+
+                       if (ies.vars) {
+                               struct ast_datastore *variablestore = NULL;
+                               struct ast_variable *var, *prev = NULL;
+                               AST_LIST_HEAD(, ast_var_t) *varlist;
+                               if ((c = iaxs[fr->callno]->owner)) {
                                        varlist = ast_calloc(1, sizeof(*varlist));
                                        variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL);
+
                                        if (variablestore && varlist) {
                                                variablestore->data = varlist;
                                                variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
                                                AST_LIST_HEAD_INIT(varlist);
+                                               ast_debug(1, "I can haz IAX vars?\n");
                                                for (var = ies.vars; var; var = var->next) {
                                                        struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
-                                                       if (prev)
+                                                       if (prev) {
                                                                ast_free(prev);
+                                                       }
                                                        prev = var;
                                                        if (!newvar) {
                                                                /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */
@@ -8387,19 +8437,36 @@ static int socket_process(struct iax2_thread *thread)
                                                                AST_LIST_INSERT_TAIL(varlist, newvar, entries);
                                                        }
                                                }
-                                               if (prev)
+                                               if (prev) {
                                                        ast_free(prev);
+                                               }
                                                ies.vars = NULL;
                                                ast_channel_datastore_add(c, variablestore);
                                        } else {
                                                ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
-                                               if (variablestore)
+                                               if (variablestore) {
                                                        ast_datastore_free(variablestore);
-                                               if (varlist)
+                                               }
+                                               if (varlist) {
                                                        ast_free(varlist);
+                                               }
+                                       }
+                               } else {
+                                       /* No channel yet, so transfer the variables directly over to the pvt,
+                                        * for later inheritance. */
+                                       ast_debug(1, "No channel, so populating IAXVARs to the pvt, as an intermediate step.\n");
+                                       for (var = ies.vars; var && var->next; var = var->next);
+                                       if (var) {
+                                               var->next = iaxs[fr->callno]->iaxvars;
+                                               iaxs[fr->callno]->iaxvars = ies.vars;
+                                               ies.vars = NULL;
                                        }
                                }
                        }
+
+                       if (ies.vars) {
+                               ast_debug(1, "I have IAX variables, but they were not processed\n");
+                       }
                }
 
                if (f.frametype == AST_FRAME_VOICE) {
@@ -8425,8 +8492,11 @@ retryowner:
                                                } else {
                                                        ast_debug(1, "Neat, somebody took away the channel at a magical time but i found it!\n");
                                                        /* Free remote variables (if any) */
-                                                       if (ies.vars)
+                                                       if (ies.vars) {
                                                                ast_variables_destroy(ies.vars);
+                                                               ast_debug(1, "I can haz iaxvars, but they is no good.  :-(\n");
+                                                               ies.vars = NULL;
+                                                       }
                                                        ast_mutex_unlock(&iaxsl[fr->callno]);
                                                        return 1;
                                                }
@@ -9155,6 +9225,7 @@ retryowner2:
                                                                        variablestore->data = varlist;
                                                                        variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
                                                                        AST_LIST_HEAD_INIT(varlist);
+                                                                       ast_debug(1, "I can haz IAX vars? w00t\n");
                                                                        for (var = ies.vars; var; var = var->next) {
                                                                                struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
                                                                                if (prev)
@@ -9215,6 +9286,7 @@ retryowner2:
                                                        AST_LIST_HEAD(, ast_var_t) *varlist;
                                                        varlist = ast_calloc(1, sizeof(*varlist));
                                                        variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL);
+                                                       ast_debug(1, "I can haz IAX vars? w00t\n");
                                                        if (variablestore && varlist) {
                                                                variablestore->data = varlist;
                                                                variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
@@ -9532,8 +9604,11 @@ retryowner2:
                                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1);
                        }
                        /* Free remote variables (if any) */
-                       if (ies.vars)
+                       if (ies.vars) {
                                ast_variables_destroy(ies.vars);
+                               ast_debug(1, "I can haz IAX vars, but they is no good :-(\n");
+                               ies.vars = NULL;
+                       }
 
                        /* Don't actually pass these frames along */
                        if ((f.subclass != IAX_COMMAND_ACK) && 
index 3427922..b9af6fd 100644 (file)
@@ -923,24 +923,32 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                                *tmp2++ = '\0';
                        else
                                tmp2 = "";
-                       /* Existing variable or new variable? */
-                       for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
-                               if (strcmp(tmp, var2->name) == 0) {
-                                       int length = strlen(var2->value) + strlen(tmp2) + 1;
-                                       char *tmp3 = alloca(length);
-                                       snprintf(tmp3, length, "%s%s", var2->value, tmp2);
-                                       var = ast_variable_new(tmp, tmp3, var2->file);
-                                       var->next = var2->next;
-                                       if (prev)
-                                               prev->next = var;
-                                       else
-                                               ies->vars = var;
-                                       ast_free(var2);
-                                       break;
+                       {
+                               struct ast_str *str = ast_str_create(16);
+                               /* Existing variable or new variable? */
+                               for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
+                                       if (strcmp(tmp, var2->name) == 0) {
+                                               ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
+                                               var = ast_variable_new(tmp, str->str, var2->file);
+                                               var->next = var2->next;
+                                               if (prev) {
+                                                       prev->next = var;
+                                               } else {
+                                                       ies->vars = var;
+                                               }
+                                               snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
+                                               errorf(tmp);
+                                               ast_free(var2);
+                                               break;
+                                       }
                                }
+                               ast_free(str);
                        }
+
                        if (!var2) {
                                var = ast_variable_new(tmp, tmp2, "");
+                               snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
+                               errorf(tmp);
                                var->next = ies->vars;
                                ies->vars = var;
                        }