From 32ce6e9a06b5483bf3e6f485ed8c62eae77f4bbf Mon Sep 17 00:00:00 2001 From: Sean Bright <sean.bright@gmail.com> Date: Wed, 11 Sep 2019 16:58:29 -0400 Subject: [PATCH] channels: Allow updating variable value When modifying an already defined variable in some channel drivers they add a new variable with the same name to the list, but that value is never used, only the first one found. Introduce ast_variable_list_replace() and use it where appropriate. ASTERISK-23756 #close Patches: setvar-multiplie.patch submitted by Michael Goryainov Change-Id: Ie1897a96c82b8945e752733612ee963686f32839 --- channels/chan_dahdi.c | 6 ++++-- channels/chan_iax2.c | 16 ++++++++++------ channels/chan_sip.c | 6 ++++-- include/asterisk/config.h | 18 ++++++++++++++++++ main/config.c | 16 ++++++++++++++++ res/res_pjsip/pjsip_configuration.c | 4 +++- 6 files changed, 55 insertions(+), 11 deletions(-) diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 0fff4b1401..2627e0977e 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -12770,8 +12770,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct ast_variable *v, *tmpvar; for (v = conf->chan.vars ; v ; v = v->next) { if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { - tmpvar->next = tmp->vars; - tmp->vars = tmpvar; + if (ast_variable_list_replace(&tmp->vars, tmpvar)) { + tmpvar->next = tmp->vars; + tmp->vars = tmpvar; + } } } } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index add593d9b2..db4bef31bf 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -7916,9 +7916,11 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i /* We found our match (use the first) */ /* copy vars */ for (v = user->vars ; v ; v = v->next) { - if((tmpvar = ast_variable_new(v->name, v->value, v->file))) { - tmpvar->next = iaxs[callno]->vars; - iaxs[callno]->vars = tmpvar; + if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { + if (ast_variable_list_replace(&iaxs[callno]->vars, tmpvar)) { + tmpvar->next = iaxs[callno]->vars; + iaxs[callno]->vars = tmpvar; + } } } /* If a max AUTHREQ restriction is in place, activate it */ @@ -13179,9 +13181,11 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st if ((varval = strchr(varname, '='))) { *varval = '\0'; varval++; - if((tmpvar = ast_variable_new(varname, varval, ""))) { - tmpvar->next = user->vars; - user->vars = tmpvar; + if ((tmpvar = ast_variable_new(varname, varval, ""))) { + if (ast_variable_list_replace(&user->vars, tmpvar)) { + tmpvar->next = user->vars; + user->vars = tmpvar; + } } } } else if (!strcasecmp(v->name, "allow")) { diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9f01b515fd..80040aee42 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -31366,8 +31366,10 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list) if ((varval = strchr(varname, '='))) { *varval++ = '\0'; if ((tmpvar = ast_variable_new(varname, varval, ""))) { - tmpvar->next = list; - list = tmpvar; + if (ast_variable_list_replace(&list, tmpvar)) { + tmpvar->next = list; + list = tmpvar; + } } } return list; diff --git a/include/asterisk/config.h b/include/asterisk/config.h index 9908b905be..1775dfe53c 100644 --- a/include/asterisk/config.h +++ b/include/asterisk/config.h @@ -948,6 +948,24 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s struct ast_variable *new_var); #define ast_variable_list_append(head, new_var) ast_variable_list_append_hint(head, NULL, new_var) +/*! + * \brief Replace a variable in the given list with a new value + * \since 13.30.0 + * + * \param head A pointer to an ast_variable * of the existing variable list head. May NOT be NULL + * but the content may be to initialize a new list. If so, upon return, this parameter will be updated + * with a pointer to the new list head. + * \param replacement The variable that replaces another variable in the list with the + * same name. + * + * \retval 0 if a variable was replaced in the list + * \retval -1 if no replacement occured + * + * \note The variable name comparison is performed case-sensitively + * \note If a variable is replaced, its memory is freed. + */ +int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement); + /*! * \brief Update variable value within a config * diff --git a/main/config.c b/main/config.c index 5660fbe963..002ae2fc99 100644 --- a/main/config.c +++ b/main/config.c @@ -665,6 +665,22 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s return curr; } +int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement) +{ + struct ast_variable *v, **prev = head; + + for (v = *head; v; prev = &v->next, v = v->next) { + if (!strcmp(v->name, replacement->name)) { + replacement->next = v->next; + *prev = replacement; + ast_free(v); + return 0; + } + } + + return -1; +} + const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var) { const char *tmp; diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 050073b80a..355b5957db 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1044,7 +1044,9 @@ static int set_var_handler(const struct aco_option *opt, return -1; } - ast_variable_list_append(&endpoint->channel_vars, new_var); + if (ast_variable_list_replace(&endpoint->channel_vars, new_var)) { + ast_variable_list_append(&endpoint->channel_vars, new_var); + } return 0; } -- GitLab