[asterisk-commits] russell: branch 1.4 r63445 - /branches/1.4/res/res_features.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue May 8 09:30:44 MST 2007


Author: russell
Date: Tue May  8 11:30:43 2007
New Revision: 63445

URL: http://svn.digium.com/view/asterisk?view=rev&rev=63445
Log:
Use a read/write lock when accessing the built-in features.

Modified:
    branches/1.4/res/res_features.c

Modified: branches/1.4/res/res_features.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/res/res_features.c?view=diff&rev=63445&r1=63444&r2=63445
==============================================================================
--- branches/1.4/res/res_features.c (original)
+++ branches/1.4/res/res_features.c Tue May  8 11:30:43 2007
@@ -878,7 +878,9 @@
 /* add atxfer and automon as undefined so you can only use em if you configure them */
 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
 
-struct ast_call_feature builtin_features[] = 
+AST_RWLOCK_DEFINE_STATIC(features_lock);
+
+static struct ast_call_feature builtin_features[] = 
  {
 	{ AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
 	{ AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
@@ -930,16 +932,14 @@
 }
 
 /*! \brief find a feature by name */
-static struct ast_call_feature *find_feature(char *name)
+static struct ast_call_feature *find_feature(const char *name)
 {
 	struct ast_call_feature *tmp;
 
-	AST_LIST_LOCK(&feature_list);
 	AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
 		if (!strcasecmp(tmp->sname, name))
 			break;
 	}
-	AST_LIST_UNLOCK(&feature_list);
 
 	return tmp;
 }
@@ -1016,23 +1016,25 @@
 static void unmap_features(void)
 {
 	int x;
+
+	ast_rwlock_wrlock(&features_lock);
 	for (x = 0; x < FEATURES_COUNT; x++)
 		strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
+	ast_rwlock_unlock(&features_lock);
 }
 
 static int remap_feature(const char *name, const char *value)
 {
-	int x;
 	int res = -1;
-	for (x = 0; x < FEATURES_COUNT; x++) {
-		if (!strcasecmp(name, builtin_features[x].sname)) {
-			ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
-			if (option_verbose > 1)
-				ast_verbose(VERBOSE_PREFIX_2 "Remapping feature %s (%s) to sequence '%s'\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
-			res = 0;
-		} else if (!strcmp(value, builtin_features[x].exten)) 
-			ast_log(LOG_WARNING, "Sequence '%s' already mapped to function %s (%s) while assigning to %s\n", value, builtin_features[x].fname, builtin_features[x].sname, name);
-	}
+	struct ast_call_feature *feature;
+
+	ast_rwlock_wrlock(&features_lock);
+	if ((feature = find_feature(name))) {
+		ast_copy_string(feature->exten, value, sizeof(feature->exten));
+		res = 0;
+	}
+	ast_rwlock_unlock(&features_lock);
+
 	return res;
 }
 
@@ -1043,6 +1045,7 @@
 	int res = FEATURE_RETURN_PASSDIGITS;
 	struct ast_call_feature *feature;
 	const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
+	char *tmp, *tok;
 
 	if (sense == FEATURE_SENSE_CHAN)
 		ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);	
@@ -1051,7 +1054,8 @@
 	if (option_debug > 2)
 		ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
 
-	for (x=0; x < FEATURES_COUNT; x++) {
+	ast_rwlock_rdlock(&features_lock);
+	for (x = 0; x < FEATURES_COUNT; x++) {
 		if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
 		    !ast_strlen_zero(builtin_features[x].exten)) {
 			/* Feature is up for consideration */
@@ -1064,27 +1068,31 @@
 			}
 		}
 	}
-
-
-	if (!ast_strlen_zero(dynamic_features)) {
-		char *tmp = ast_strdupa(dynamic_features);
-		char *tok;
-
-		while ((tok = strsep(&tmp, "#")) != NULL) {
-			feature = find_feature(tok);
+	ast_rwlock_unlock(&features_lock);
+
+	if (ast_strlen_zero(dynamic_features))
+		return res;
+
+	tmp = ast_strdupa(dynamic_features);
+
+	while ((tok = strsep(&tmp, "#"))) {
+		ast_rwlock_rdlock(&features_lock);
+		if (!(feature = find_feature(tok))) {
+			ast_rwlock_unlock(&features_lock);
+			continue;
+		}
 			
-			if (feature) {
-				/* Feature is up for consideration */
-				if (!strcmp(feature->exten, code)) {
-					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
-					res = feature->operation(chan, peer, config, code, sense);
-					break;
-				} else if (!strncmp(feature->exten, code, strlen(code))) {
-					res = FEATURE_RETURN_STOREDIGITS;
-				}
-			}
-		}
+		/* Feature is up for consideration */
+		if (!strcmp(feature->exten, code)) {
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
+			res = feature->operation(chan, peer, config, code, sense);
+			ast_rwlock_unlock(&features_lock);
+			break;
+		} else if (!strncmp(feature->exten, code, strlen(code)))
+			res = FEATURE_RETURN_STOREDIGITS;
+
+		ast_rwlock_unlock(&features_lock);
 	}
 	
 	return res;
@@ -1094,16 +1102,20 @@
 {
 	int x;
 	
-	ast_clear_flag(config, AST_FLAGS_ALL);	
+	ast_clear_flag(config, AST_FLAGS_ALL);
+
+	ast_rwlock_rdlock(&features_lock);
 	for (x = 0; x < FEATURES_COUNT; x++) {
-		if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
-			if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
-				ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
-
-			if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
-				ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
-		}
-	}
+		if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
+			continue;
+
+		if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
+			ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
+
+		if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
+			ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
+	}
+	ast_rwlock_unlock(&features_lock);
 	
 	if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
 		const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
@@ -1115,12 +1127,14 @@
 
 			/* while we have a feature */
 			while ((tok = strsep(&tmp, "#"))) {
+				ast_rwlock_rdlock(&features_lock);
 				if ((feature = find_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
 					if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
 						ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
 					if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
 						ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
 				}
+				ast_rwlock_unlock(&features_lock);
 			}
 		}
 	}
@@ -1156,7 +1170,8 @@
 
 			ast_indicate(caller, AST_CONTROL_RINGING);
 			/* support dialing of the featuremap disconnect code while performing an attended tranfer */
-			for (x=0; x < FEATURES_COUNT; x++) {
+			ast_rwlock_rdlock(&features_lock);
+			for (x = 0; x < FEATURES_COUNT; x++) {
 				if (strcasecmp(builtin_features[x].sname, "disconnect"))
 					continue;
 
@@ -1166,6 +1181,7 @@
 				memset(dialed_code, 0, len);
 				break;
 			}
+			ast_rwlock_unlock(&features_lock);
 			x = 0;
 			started = ast_tvnow();
 			to = timeout;
@@ -1917,7 +1933,6 @@
 static int handle_showfeatures(int fd, int argc, char *argv[])
 {
 	int i;
-	int fcount;
 	struct ast_call_feature *feature;
 	char format[] = "%-25s %-7s %-7s\n";
 
@@ -1926,23 +1941,20 @@
 
 	ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());		/* default hardcoded above, so we'll hardcode it here */
 
-	fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
-
-	for (i = 0; i < fcount; i++)
-	{
+	ast_rwlock_rdlock(&features_lock);
+	for (i = 0; i < FEATURES_COUNT; i++)
 		ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
-	}
+	ast_rwlock_unlock(&features_lock);
+
 	ast_cli(fd, "\n");
 	ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
 	ast_cli(fd, format, "---------------", "-------", "-------");
-	if (AST_LIST_EMPTY(&feature_list)) {
+	if (AST_LIST_EMPTY(&feature_list))
 		ast_cli(fd, "(none)\n");
-	}
 	else {
 		AST_LIST_LOCK(&feature_list);
-		AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
+		AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
 			ast_cli(fd, format, feature->sname, "no def", feature->exten);	
-		}
 		AST_LIST_UNLOCK(&feature_list);
 	}
 	ast_cli(fd, "\nCall parking\n");



More information about the asterisk-commits mailing list