diff --git a/include/asterisk/indications.h b/include/asterisk/indications.h index 6b55d90aaf..188baa29b7 100644 --- a/include/asterisk/indications.h +++ b/include/asterisk/indications.h @@ -59,29 +59,34 @@ struct tone_zone { }; /* set the default tone country */ -extern int ast_set_indication_country(const char *country); +int ast_set_indication_country(const char *country); /* locate tone_zone, given the country. if country == NULL, use the default country */ -extern struct tone_zone *ast_get_indication_zone(const char *country); +struct tone_zone *ast_get_indication_zone(const char *country); /* locate a tone_zone_sound, given the tone_zone. if tone_zone == NULL, use the default tone_zone */ -extern struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication); +struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication); /* add a new country, if country exists, it will be replaced. */ -extern int ast_register_indication_country(struct tone_zone *country); +int ast_register_indication_country(struct tone_zone *country); /* remove an existing country and all its indications, country must exist */ -extern int ast_unregister_indication_country(const char *country); +int ast_unregister_indication_country(const char *country); /* add a new indication to a tone_zone. tone_zone must exist. if the indication already * exists, it will be replaced. */ -extern int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist); +int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist); /* remove an existing tone_zone's indication. tone_zone must exist */ -extern int ast_unregister_indication(struct tone_zone *zone, const char *indication); +int ast_unregister_indication(struct tone_zone *zone, const char *indication); /* Start a tone-list going */ int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible); /*! Stop the tones from playing */ void ast_playtones_stop(struct ast_channel *chan); +/* support for walking through a list of indications */ +struct tone_zone *ast_walk_indications(const struct tone_zone *cur); + +#if 0 extern struct tone_zone *tone_zones; extern ast_mutex_t tzlock; +#endif #endif /* _ASTERISK_INDICATIONS_H */ diff --git a/indications.c b/indications.c index 2d2ca68962..9b632de98a 100644 --- a/indications.c +++ b/indications.c @@ -330,22 +330,28 @@ void ast_playtones_stop(struct ast_channel *chan) /*--------------------------------------------*/ -struct tone_zone *tone_zones; +static struct tone_zone *tone_zones; static struct tone_zone *current_tonezone; /* Protect the tone_zones list (highly unlikely that two things would change * it at the same time, but still! */ -AST_MUTEX_DEFINE_EXPORTED(tzlock); -/* XXX note - this is the only instance of AST_MUTEX_DEFINE_EXPORTED() - * in the entire asterisk code base, and should be replaced by a static one. - * The mutex is declared exported because it is accessed - * by other files, namely res/snmp/agent.c and res/res_indications.c. - * However there are also unprotected accesses to the list, because - * some of the functions below export pointers to the elements, so - * the entire mechanism is useless. - * This needs to be fixed by providing functions to navigate in the - * list, and refcounts to prevent entries from being destroyed. - */ +AST_MUTEX_DEFINE_STATIC(tzlock); + +struct tone_zone *ast_walk_indications(const struct tone_zone *cur) +{ + struct tone_zone *tz; + + if (cur == NULL) + return tone_zones; + ast_mutex_lock(&tzlock); + for (tz = tone_zones; tz; tz = tz->next) + if (tz == cur) + break; + if (tz) + tz = tz->next; + ast_mutex_unlock(&tzlock); + return tz; +} /* Set global indication country */ int ast_set_indication_country(const char *country) diff --git a/res/res_indications.c b/res/res_indications.c index 1188b05865..cb3a766ecd 100644 --- a/res/res_indications.c +++ b/res/res_indications.c @@ -149,26 +149,20 @@ static int handle_remove_indication(int fd, int argc, char *argv[]) */ static int handle_show_indications(int fd, int argc, char *argv[]) { - struct tone_zone *tz; + struct tone_zone *tz = NULL; char buf[256]; int found_country = 0; - if (ast_mutex_lock(&tzlock)) { - ast_log(LOG_WARNING, "Unable to lock tone_zones list\n"); - return 0; - } if (argc == 2) { /* no arguments, show a list of countries */ ast_cli(fd,"Country Alias Description\n" "===========================\n"); - for (tz=tone_zones; tz; tz=tz->next) { + while ( (tz = ast_walk_indications(tz) ) ) ast_cli(fd,"%-7.7s %-7.7s %s\n", tz->country, tz->alias, tz->description); - } - ast_mutex_unlock(&tzlock); return 0; } /* there was a request for specific country(ies), lets humor them */ - for (tz=tone_zones; tz; tz=tz->next) { + while ( (tz = ast_walk_indications(tz) ) ) { int i,j; for (i=2; icountry,argv[i])==0 && @@ -183,7 +177,8 @@ static int handle_show_indications(int fd, int argc, char *argv[]) for (i=0; inrringcadence; i++) { j += snprintf(buf+j,sizeof(buf)-j,"%d,",tz->ringcadence[i]); } - if (tz->nrringcadence) j--; + if (tz->nrringcadence) + j--; ast_copy_string(buf+j,"\n",sizeof(buf)-j); ast_cli(fd,buf); for (ts=tz->tones; ts; ts=ts->next) @@ -194,7 +189,6 @@ static int handle_show_indications(int fd, int argc, char *argv[]) } if (!found_country) ast_cli(fd,"No countries matched your criteria.\n"); - ast_mutex_unlock(&tzlock); return -1; } diff --git a/res/snmp/agent.c b/res/snmp/agent.c index 740f5c10e1..1826010771 100644 --- a/res/snmp/agent.c +++ b/res/snmp/agent.c @@ -631,22 +631,16 @@ static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *lengt int exact, size_t *var_len, WriteMethod **write_method) { static unsigned long long_ret; - struct tone_zone *tz; + struct tone_zone *tz = NULL; if (header_generic(vp, name, length, exact, var_len, write_method)) return NULL; switch (vp->magic) { case ASTINDCOUNT: - if (ast_mutex_lock(&tzlock)) { - ast_log(LOG_WARNING, "Unable to lock tone_zones list\n"); - snmp_log(LOG_ERR, "Unable to lock tone_zones list in ast_var_indications\n"); - return NULL; - } long_ret = 0; - for (tz = tone_zones; tz; tz = tz->next) + while ( (tz = ast_walk_indications(tz)) ) long_ret++; - ast_mutex_unlock(&tzlock); return (u_char *)&long_ret; case ASTINDCURRENT: @@ -667,21 +661,15 @@ static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t int exact, size_t *var_len, WriteMethod **write_method) { static unsigned long long_ret; - struct tone_zone *tz; + struct tone_zone *tz = NULL; int i; if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) return NULL; - if (ast_mutex_lock(&tzlock)) { - ast_log(LOG_WARNING, "Unable to lock tone_zones list\n"); - snmp_log(LOG_ERR, "Unable to lock tone_zones list in ast_var_indications_table\n"); - return NULL; - } i = name[*length - 1] - 1; - for (tz = tone_zones; tz && i; tz = tz->next) - i--; - ast_mutex_unlock(&tzlock); + while ( (tz = ast_walk_indications(tz)) && i ) + i--; if (tz == NULL) return NULL;