[svn-commits] sgriepentrog: branch 12 r402387 - in /branches/12: include/asterisk/ main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Nov 1 16:49:38 CDT 2013


Author: sgriepentrog
Date: Fri Nov  1 16:49:35 2013
New Revision: 402387

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=402387
Log:
Manager: Add equivalent AMI actions for the bridge CLI commands.

Adds the following AMI events, closely following their CLI counterparts:

BridgeDestroy
BridgeKick
BridgeTechnologyList
BridgeTechnologySuspend
BridgeTechnologyUnsuspend

BridgeDestroy kicks an entire bridge, where BridgeKick kicks just one
channel off the bridge. When kicking a channel, specifying the bridge
also (optional) insures it is not removed from the wrong bridge.  The
BridgeTechnology events allow viewing and changing suspension status,
which affects only subsequent not active bridging.

(closes ASTERISK-22356)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2973/



Modified:
    branches/12/include/asterisk/bridge.h
    branches/12/main/bridge.c
    branches/12/main/manager_bridges.c

Modified: branches/12/include/asterisk/bridge.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/bridge.h?view=diff&rev=402387&r1=402386&r2=402387
==============================================================================
--- branches/12/include/asterisk/bridge.h (original)
+++ branches/12/include/asterisk/bridge.h Fri Nov  1 16:49:35 2013
@@ -1020,6 +1020,17 @@
  */
 void ast_bridge_features_remove(struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags flags);
 
+/*!
+ * \brief Find bridge by id
+ * \since 12.0.0
+ *
+ * \param bridge_id Bridge identifier
+ *
+ * \return NULL bridge not found
+ * \return non-NULL reference to bridge
+ */
+struct ast_bridge *ast_bridge_find_by_id(const char *bridge_id);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: branches/12/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/bridge.c?view=diff&rev=402387&r1=402386&r2=402387
==============================================================================
--- branches/12/main/bridge.c (original)
+++ branches/12/main/bridge.c Fri Nov  1 16:49:35 2013
@@ -26,6 +26,48 @@
 /*** MODULEINFO
 	<support_level>core</support_level>
  ***/
+
+/*** DOCUMENTATION
+	<manager name="BridgeTechnologyList" language="en_US">
+		<synopsis>
+			List available bridging technologies and their statuses.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+		</syntax>
+		<description>
+			<para>Returns detailed information about the available bridging technologies.</para>
+		</description>
+	</manager>
+	<manager name="BridgeTechnologySuspend" language="en_US">
+		<synopsis>
+			Suspend a bridging technology.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+			<parameter name="BridgeTechnology" required="true">
+				<para>The name of the bridging technology to suspend.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Marks a bridging technology as suspended, which prevents subsequently created bridges from using it.</para>
+		</description>
+	</manager>
+	<manager name="BridgeTechnologyUnsuspend" language="en_US">
+		<synopsis>
+			Unsuspend a bridging technology.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+			<parameter name="BridgeTechnology" required="true">
+				<para>The name of the bridging technology to unsuspend.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Clears a previously suspended bridging technology, which allows subsequently created bridges to use it.</para>
+		</description>
+	</manager>
+***/
 
 #include "asterisk.h"
 
@@ -4485,6 +4527,11 @@
 	return cmp;
 }
 
+struct ast_bridge *ast_bridge_find_by_id(const char *bridge_id)
+{
+	return ao2_find(bridges, bridge_id, OBJ_SEARCH_KEY);
+}
+
 struct bridge_complete {
 	/*! Nth match to return. */
 	int state;
@@ -4673,7 +4720,7 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	bridge = ao2_find(bridges, a->argv[2], OBJ_KEY);
+	bridge = ast_bridge_find_by_id(a->argv[2]);
 	if (!bridge) {
 		ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
 		return CLI_SUCCESS;
@@ -4692,7 +4739,7 @@
 	int which;
 	int wordlen;
 
-	bridge = ao2_find(bridges, bridge_name, OBJ_KEY);
+	bridge = ast_bridge_find_by_id(bridge_name);
 	if (!bridge) {
 		return NULL;
 	}
@@ -4739,7 +4786,7 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	bridge = ao2_find(bridges, a->argv[2], OBJ_KEY);
+	bridge = ast_bridge_find_by_id(a->argv[2]);
 	if (!bridge) {
 		ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);
 		return CLI_SUCCESS;
@@ -4891,13 +4938,102 @@
 static struct ast_cli_entry bridge_cli[] = {
 	AST_CLI_DEFINE(handle_bridge_show_all, "List all bridges"),
 	AST_CLI_DEFINE(handle_bridge_show_specific, "Show information about a bridge"),
-/* XXX ASTERISK-22356 need AMI action equivalents to the following CLI commands. */
 	AST_CLI_DEFINE(handle_bridge_destroy_specific, "Destroy a bridge"),
 	AST_CLI_DEFINE(handle_bridge_kick_channel, "Kick a channel from a bridge"),
 	AST_CLI_DEFINE(handle_bridge_technology_show, "List registered bridge technologies"),
 	AST_CLI_DEFINE(handle_bridge_technology_suspend, "Suspend/unsuspend a bridge technology"),
 };
 
+
+static int handle_manager_bridge_tech_suspend(struct mansession *s, const struct message *m, int suspend)
+{
+	const char *name = astman_get_header(m, "BridgeTechnology");
+	struct ast_bridge_technology *cur;
+	int successful = 0;
+
+	if (ast_strlen_zero(name)) {
+		astman_send_error(s, m, "BridgeTechnology must be provided");
+		return 0;
+	}
+
+	AST_RWLIST_RDLOCK(&bridge_technologies);
+	AST_RWLIST_TRAVERSE(&bridge_technologies, cur, entry) {
+
+		if (!strcasecmp(cur->name, name)) {
+			successful = 1;
+			if (suspend) {
+				ast_bridge_technology_suspend(cur);
+			} else {
+				ast_bridge_technology_unsuspend(cur);
+			}
+			break;
+		}
+	}
+	AST_RWLIST_UNLOCK(&bridge_technologies);
+	if (!successful) {
+		astman_send_error(s, m, "BridgeTechnology not found");
+		return 0;
+	}
+
+	astman_send_ack(s, m, (suspend ? "Suspended bridge technology" : "Unsuspended bridge technology"));
+	return 0;
+}
+
+static int manager_bridge_tech_suspend(struct mansession *s, const struct message *m)
+{
+	return handle_manager_bridge_tech_suspend(s, m, 1);
+}
+
+static int manager_bridge_tech_unsuspend(struct mansession *s, const struct message *m)
+{
+	return handle_manager_bridge_tech_suspend(s, m, 0);
+}
+
+static int manager_bridge_tech_list(struct mansession *s, const struct message *m)
+{
+	const char *id = astman_get_header(m, "ActionID");
+	RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
+	struct ast_bridge_technology *cur;
+
+	if (!id_text) {
+		astman_send_error(s, m, "Internal error");
+		return -1;
+	}
+
+	if (!ast_strlen_zero(id)) {
+		ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);
+	}
+
+	astman_send_ack(s, m, "Bridge technology listing will follow");
+
+	AST_RWLIST_RDLOCK(&bridge_technologies);
+	AST_RWLIST_TRAVERSE(&bridge_technologies, cur, entry) {
+		const char *type;
+
+		type = tech_capability2str(cur->capabilities);
+
+		astman_append(s,
+			"Event: BridgeTechnologyListItem\r\n"
+			"BridgeTechnology: %s\r\n"
+			"BridgeType: %s\r\n"
+			"BridgePriority: %d\r\n"
+			"BridgeSuspended: %s\r\n"
+			"%s"
+			"\r\n",
+			cur->name, type, cur->preference, AST_YESNO(cur->suspended),
+			ast_str_buffer(id_text));
+	}
+	AST_RWLIST_UNLOCK(&bridge_technologies);
+
+	astman_append(s,
+		"Event: BridgeTechnologyListComplete\r\n"
+		"%s"
+		"\r\n",
+		ast_str_buffer(id_text));
+
+	return 0;
+}
+
 /*!
  * \internal
  * \brief Print bridge object key (name).
@@ -4929,6 +5065,9 @@
  */
 static void bridge_shutdown(void)
 {
+	ast_manager_unregister("BridgeTechnologyList");
+	ast_manager_unregister("BridgeTechnologySuspend");
+	ast_manager_unregister("BridgeTechnologyUnsuspend");
 	ast_cli_unregister_multiple(bridge_cli, ARRAY_LEN(bridge_cli));
 	ao2_container_unregister("bridges");
 	ao2_cleanup(bridges);
@@ -4961,5 +5100,9 @@
 
 	ast_cli_register_multiple(bridge_cli, ARRAY_LEN(bridge_cli));
 
+	ast_manager_register_xml_core("BridgeTechnologyList", 0, manager_bridge_tech_list);
+	ast_manager_register_xml_core("BridgeTechnologySuspend", 0, manager_bridge_tech_suspend);
+	ast_manager_register_xml_core("BridgeTechnologyUnsuspend", 0, manager_bridge_tech_unsuspend);
+
 	return 0;
 }

Modified: branches/12/main/manager_bridges.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/manager_bridges.c?view=diff&rev=402387&r1=402386&r2=402387
==============================================================================
--- branches/12/main/manager_bridges.c (original)
+++ branches/12/main/manager_bridges.c Fri Nov  1 16:49:35 2013
@@ -101,6 +101,39 @@
 			<para>Returns detailed information about a bridge and the channels in it.</para>
 		</description>
 	</manager>
+	<manager name="BridgeDestroy" language="en_US">
+		<synopsis>
+			Destroy a bridge.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+			<parameter name="BridgeUniqueid" required="true">
+				<para>The unique ID of the bridge to destroy.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Deletes the bridge, causing channels to continue or hang up.</para>
+		</description>
+	</manager>
+	<manager name="BridgeKick" language="en_US">
+		<synopsis>
+			Kick a channel from a bridge.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+			<parameter name="BridgeUniqueid" required="false">
+				<para>The unique ID of the bridge containing the channel to
+				destroy.  This parameter can be omitted, or supplied to insure
+				that the channel is not removed from the wrong bridge.</para>
+			</parameter>
+			<parameter name="Channel" required="true">
+				<para>The channel to kick out of a bridge.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>The channel is removed from the bridge.</para>
+		</description>
+	</manager>
  ***/
 
 /*! \brief The \ref stasis subscription returned by the forwarding of the channel topic
@@ -419,7 +452,7 @@
 
 	if (ast_strlen_zero(bridge_uniqueid)) {
 		astman_send_error(s, m, "BridgeUniqueid must be provided");
-		return -1;
+		return 0;
 	}
 
 	if (!ast_strlen_zero(id)) {
@@ -429,7 +462,7 @@
 	msg = stasis_cache_get(ast_bridge_cache(), ast_bridge_snapshot_type(), bridge_uniqueid);
 	if (!msg) {
 		astman_send_error(s, m, "Specified BridgeUniqueid not found");
-		return -1;
+		return 0;
 	}
 
 	astman_send_ack(s, m, "Bridge channel listing will follow");
@@ -450,6 +483,72 @@
 	return 0;
 }
 
+static int manager_bridge_destroy(struct mansession *s, const struct message *m)
+{
+	const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
+	struct ast_bridge *bridge;
+
+	if (ast_strlen_zero(bridge_uniqueid)) {
+		astman_send_error(s, m, "BridgeUniqueid must be provided");
+		return 0;
+	}
+
+	bridge = ast_bridge_find_by_id(bridge_uniqueid);
+	if (!bridge) {
+		astman_send_error(s, m, "Specified BridgeUniqueid not found");
+		return 0;
+	}
+	ast_bridge_destroy(bridge, 0);
+
+	astman_send_ack(s, m, "Bridge has been destroyed");
+
+	return 0;
+}
+
+static int manager_bridge_kick(struct mansession *s, const struct message *m)
+{
+	const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
+	const char *channel_name = astman_get_header(m, "Channel");
+	RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_channel *, channel, NULL, ao2_cleanup);
+
+	if (ast_strlen_zero(channel_name)) {
+		astman_send_error(s, m, "Channel must be provided");
+		return 0;
+	}
+
+	channel = ast_channel_get_by_name(channel_name);
+	if (!channel) {
+		astman_send_error(s, m, "Channel does not exist");
+		return 0;
+	}
+
+	if (ast_strlen_zero(bridge_uniqueid)) {
+		/* get the bridge from the channel */
+		ast_channel_lock(channel);
+		bridge = ast_channel_get_bridge(channel);
+		ast_channel_unlock(channel);
+		if (!bridge) {
+			astman_send_error(s, m, "Channel is not in a bridge");
+			return 0;
+		}
+	} else {
+		bridge = ast_bridge_find_by_id(bridge_uniqueid);
+		if (!bridge) {
+			astman_send_error(s, m, "Bridge not found");
+			return 0;
+		}
+	}
+
+	if (ast_bridge_kick(bridge, channel)) {
+		astman_send_error(s, m, "Channel kick from bridge failed");
+		return 0;
+	}
+
+	astman_send_ack(s, m, "Channel has been kicked");
+	return 0;
+}
+
 static void manager_bridging_cleanup(void)
 {
 	stasis_forward_cancel(topic_forwarder);
@@ -460,6 +559,8 @@
 {
 	ast_manager_unregister("BridgeList");
 	ast_manager_unregister("BridgeInfo");
+	ast_manager_unregister("BridgeDestroy");
+	ast_manager_unregister("BridgeKick");
 }
 
 int manager_bridging_init(void)
@@ -510,6 +611,8 @@
 
 	ret |= ast_manager_register_xml_core("BridgeList", 0, manager_bridges_list);
 	ret |= ast_manager_register_xml_core("BridgeInfo", 0, manager_bridge_info);
+	ret |= ast_manager_register_xml_core("BridgeDestroy", 0, manager_bridge_destroy);
+	ret |= ast_manager_register_xml_core("BridgeKick", 0, manager_bridge_kick);
 
 	/* If somehow we failed to add any routes, just shut down the whole
 	 * thing and fail it.




More information about the svn-commits mailing list