Index: channels/chan_iax2.c =================================================================== --- channels/chan_iax2.c (revision 140395) +++ channels/chan_iax2.c (working copy) @@ -655,7 +655,10 @@ 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) */ @@ -3742,10 +3745,12 @@ /* 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); @@ -4251,6 +4256,42 @@ 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)) { @@ -8337,8 +8378,10 @@ } 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; @@ -8358,20 +8401,27 @@ 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. */ @@ -8380,19 +8430,36 @@ 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) { @@ -8418,8 +8485,11 @@ } 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; } @@ -9148,6 +9218,7 @@ 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) @@ -9208,6 +9279,7 @@ 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; @@ -9525,8 +9597,11 @@ 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: channels/iax2-parser.c =================================================================== --- channels/iax2-parser.c (revision 140395) +++ channels/iax2-parser.c (working copy) @@ -923,24 +923,32 @@ *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; } Index: apps/app_dial.c =================================================================== --- apps/app_dial.c (revision 140395) +++ apps/app_dial.c (working copy) @@ -1492,6 +1492,7 @@ /* 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)";