[svn-commits] gtjoseph: branch 12 r422090 - /branches/12/apps/app_confbridge.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Aug 26 18:18:37 CDT 2014


Author: gtjoseph
Date: Tue Aug 26 18:18:32 2014
New Revision: 422090

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=422090
Log:
confbridge: Make kick, mute and unmute handle channel targets consistently.

Kick, mute and unmute were a little inconsistent in their handling of channel
targets.  This patch cleans that up by insuring they all handle the 'all'
target consistently and adds the 'participants' target which acts on
non-admins.  Documentation for kick was also cleaned up as it never
supported partial channel names.

Tested by: George Joseph
Review: https://reviewboard.asterisk.org/r/3944/

Modified:
    branches/12/apps/app_confbridge.c

Modified: branches/12/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/apps/app_confbridge.c?view=diff&rev=422090&r1=422089&r2=422090
==============================================================================
--- branches/12/apps/app_confbridge.c (original)
+++ branches/12/apps/app_confbridge.c Tue Aug 26 18:18:32 2014
@@ -196,6 +196,8 @@
 			<parameter name="Conference" required="true" />
 			<parameter name="Channel" required="true">
 				<para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
+				<para>If this parameter is "all", all channels will be muted.</para>
+				<para>If this parameter is "participants", all non-admin channels will be muted.</para>
 			</parameter>
 		</syntax>
 		<description>
@@ -210,6 +212,8 @@
 			<parameter name="Conference" required="true" />
 			<parameter name="Channel" required="true">
 				<para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
+				<para>If this parameter is "all", all channels will be unmuted.</para>
+				<para>If this parameter is "participants", all non-admin channels will be unmuted.</para>
 			</parameter>
 		</syntax>
 		<description>
@@ -223,8 +227,8 @@
 			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
 			<parameter name="Conference" required="true" />
 			<parameter name="Channel" required="true" >
-				<para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
 				<para>If this parameter is "all", all channels will be kicked from the conference.</para>
+				<para>If this parameter is "participants", all non-admin channels will be kicked from the conference.</para>
 			</parameter>
 		</syntax>
 		<description>
@@ -2137,33 +2141,45 @@
 	return 0;
 }
 
-static int kick_conference_participant(struct confbridge_conference *conference, const char *channel)
+static int kick_conference_participant(struct confbridge_conference *conference,
+	const char *channel)
 {
 	int res = -1;
+	int match;
 	struct confbridge_user *user = NULL;
+	int all = !strcasecmp("all", channel);
+	int participants = !strcasecmp("participants", channel);
 
 	SCOPED_AO2LOCK(bridge_lock, conference);
 
 	AST_LIST_TRAVERSE(&conference->active_list, user, list) {
-		if (!strcasecmp(ast_channel_name(user->chan), channel) && !user->kicked) {
-			user->kicked = 1;
-			ast_bridge_remove(conference->bridge, user->chan);
-			return 0;
-		} else if (!strcasecmp("all", channel)) {
+		if (user->kicked) {
+			continue;
+		}
+		match = !strcasecmp(channel, ast_channel_name(user->chan));
+		if (match || all
+				|| (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
 			user->kicked = 1;
 			ast_bridge_remove(conference->bridge, user->chan);
 			res = 0;
+			if (match) {
+				return res;
+			}
 		}
 	}
 	AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
-		if (!strcasecmp(ast_channel_name(user->chan), channel) && !user->kicked) {
-			user->kicked = 1;
-			ast_bridge_remove(conference->bridge, user->chan);
-			return 0;
-		} else if (!strcasecmp("all", channel)) {
+		if (user->kicked) {
+			continue;
+		}
+		match = !strcasecmp(channel, ast_channel_name(user->chan));
+		if (match || all
+				|| (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
 			user->kicked = 1;
 			ast_bridge_remove(conference->bridge, user->chan);
 			res = 0;
+			if (match) {
+				return res;
+			}
 		}
 	}
 
@@ -2205,10 +2221,13 @@
 		return NULL;
 	}
 
-	if (!state) {
+	if (!strncasecmp("all", word, wordlen) && ++which > state) {
 		return ast_strdup("all");
 	}
-	state--;
+
+	if (!strncasecmp("participants", word, wordlen) && ++which > state) {
+		return ast_strdup("participants");
+	}
 
 	{
 		SCOPED_AO2LOCK(bridge_lock, conference);
@@ -2239,7 +2258,8 @@
 		e->command = "confbridge kick";
 		e->usage =
 			"Usage: confbridge kick <conference> <channel>\n"
-			"       Kicks a channel out of the conference bridge (all to kick everyone).\n";
+			"       Kicks a channel out of the conference bridge.\n"
+			"             (all to kick everyone, participants to kick non-admins).\n";
 		return NULL;
 	case CLI_GENERATE:
 		if (a->pos == 2) {
@@ -2263,10 +2283,14 @@
 	not_found = kick_conference_participant(conference, a->argv[3]);
 	ao2_ref(conference, -1);
 	if (not_found) {
-		ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
+		if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
+			ast_cli(a->fd, "No participants found!\n");
+		} else {
+			ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
+		}
 		return CLI_SUCCESS;
 	}
-	ast_cli(a->fd, "Participant '%s' kicked out of conference '%s'\n", a->argv[3], a->argv[2]);
+	ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
 	return CLI_SUCCESS;
 }
 
@@ -2399,59 +2423,78 @@
 }
 
 /* \internal
+ * \brief Mute/unmute a single user.
+ */
+static void generic_mute_unmute_user(struct confbridge_conference *conference, struct confbridge_user *user, int mute)
+{
+	/* Set user level mute request. */
+	user->muted = mute ? 1 : 0;
+
+	conf_update_user_mute(user);
+	ast_test_suite_event_notify("CONF_MUTE",
+		"Message: participant %s %s\r\n"
+		"Conference: %s\r\n"
+		"Channel: %s",
+		ast_channel_name(user->chan),
+		mute ? "muted" : "unmuted",
+		conference->b_profile.name,
+		ast_channel_name(user->chan));
+	if (mute) {
+		send_mute_event(user->chan, conference);
+	} else {
+		send_unmute_event(user->chan, conference);
+	}
+}
+
+/* \internal
  * \brief finds a conference user by channel name and mutes/unmutes them.
  *
  * \retval 0 success
  * \retval -1 conference not found
  * \retval -2 user not found
  */
-static int generic_mute_unmute_helper(int mute, const char *conference_name, const char *chan_name)
-{
-	struct confbridge_conference *conference;
+static int generic_mute_unmute_helper(int mute, const char *conference_name,
+	const char *chan_name)
+{
+	RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
 	struct confbridge_user *user;
-	int res = 0;
+	int all = !strcasecmp("all", chan_name);
+	int participants = !strcasecmp("participants", chan_name);
+	int res = -2;
 
 	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		return -1;
 	}
-	ao2_lock(conference);
-	AST_LIST_TRAVERSE(&conference->active_list, user, list) {
-		if (!strncmp(chan_name, ast_channel_name(user->chan), strlen(chan_name))) {
-			break;
-		}
-	}
-	if (!user) {
-		/* user is not in the active list so check the waiting list as well */
+
+	{
+		SCOPED_AO2LOCK(bridge_lock, conference);
+		AST_LIST_TRAVERSE(&conference->active_list, user, list) {
+			int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
+				strlen(chan_name));
+			if (match || all
+				|| (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
+				generic_mute_unmute_user(conference, user, mute);
+				res = 0;
+				if (match) {
+					return res;
+				}
+			}
+		}
+
 		AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
-			if (!strncmp(chan_name, ast_channel_name(user->chan), strlen(chan_name))) {
-				break;
+			int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
+				strlen(chan_name));
+			if (match || all
+				|| (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
+				generic_mute_unmute_user(conference, user, mute);
+				res = 0;
+				if (match) {
+					return res;
+				}
 			}
 		}
 	}
-	if (user) {
-		/* Set user level mute request. */
-		user->muted = mute ? 1 : 0;
-
-		conf_update_user_mute(user);
-		ast_test_suite_event_notify("CONF_MUTE",
-			"Message: participant %s %s\r\n"
-			"Conference: %s\r\n"
-			"Channel: %s",
-			ast_channel_name(user->chan),
-			mute ? "muted" : "unmuted",
-			conference->b_profile.name,
-			ast_channel_name(user->chan));
-		if (mute) {
-			send_mute_event(user->chan, conference);
-		} else {
-			send_unmute_event(user->chan, conference);
-		}
-	} else {
-		res = -2;;
-	}
-	ao2_unlock(conference);
-	ao2_ref(conference, -1);
 
 	return res;
 }
@@ -2464,7 +2507,11 @@
 		ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
 		return -1;
 	} else if (res == -2) {
-		ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
+		if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
+			ast_cli(a->fd, "No participants found in conference %s\n", a->argv[2]);
+		} else {
+			ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
+		}
 		return -1;
 	}
 	ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
@@ -2479,6 +2526,7 @@
 		e->usage =
 			"Usage: confbridge mute <conference> <channel>\n"
 			"       Mute a channel in a conference.\n"
+			"              (all to mute everyone, participants to mute non-admins)\n"
 			"       If the specified channel is a prefix,\n"
 			"       the action will be taken on the first\n"
 			"       matching channel.\n";
@@ -2509,6 +2557,7 @@
 		e->usage =
 			"Usage: confbridge unmute <conference> <channel>\n"
 			"       Unmute a channel in a conference.\n"
+			"              (all to unmute everyone, participants to unmute non-admins)\n"
 			"       If the specified channel is a prefix,\n"
 			"       the action will be taken on the first\n"
 			"       matching channel.\n";
@@ -2679,8 +2728,8 @@
 static struct ast_cli_entry cli_confbridge[] = {
 	AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
 	AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
-	AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
-	AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."),
+	AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute participants."),
+	AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute participants."),
 	AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
 	AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
 	AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),




More information about the svn-commits mailing list