From 48864ab877d4e9038f3f8c0e119ab7e02c07523c Mon Sep 17 00:00:00 2001
From: Luigi Rizzo <rizzo@icir.org>
Date: Thu, 30 Mar 2006 17:10:11 +0000
Subject: [PATCH] do not export the tzlock and the list head, and introduce a
 new method, ast_walk_indications(), to walk through the list of indications.
 The new method returns an unlocked record, which is no different from the
 behaviour of other existing methods in indications.c (i.e. they all need to
 be fixed, with refcounts or some similar method).

Note that ast_walk_indications() uses the pointer argument only as a
search key, so its implementation is completely safe.

In turn, this change allows the removal of AST_MUTEX_DEFINE_EXPORTED.



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@16532 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 include/asterisk/indications.h | 19 ++++++++++++-------
 indications.c                  | 30 ++++++++++++++++++------------
 res/res_indications.c          | 16 +++++-----------
 res/snmp/agent.c               | 22 +++++-----------------
 4 files changed, 40 insertions(+), 47 deletions(-)

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; i<argc; i++) {
 			if (strcasecmp(tz->country,argv[i])==0 &&
@@ -183,7 +177,8 @@ static int handle_show_indications(int fd, int argc, char *argv[])
 				for (i=0; i<tz->nrringcadence; 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;
 
-- 
GitLab