[asterisk-commits] kmoore: branch kmoore/bridge_construction-cel_channels r389327 - in /team/kmo...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon May 20 15:47:40 CDT 2013


Author: kmoore
Date: Mon May 20 15:47:36 2013
New Revision: 389327

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389327
Log:
Refactor to avoid ast_bridged_channel

This also includes a function (ast_channel_snapshot_get_latest) swiped
from dlee.

Modified:
    team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_bridging.h
    team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_channels.h
    team/kmoore/bridge_construction-cel_channels/main/cel.c
    team/kmoore/bridge_construction-cel_channels/main/stasis_bridging.c
    team/kmoore/bridge_construction-cel_channels/main/stasis_channels.c

Modified: team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_bridging.h?view=diff&rev=389327&r1=389326&r2=389327
==============================================================================
--- team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_bridging.h (original)
+++ team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_bridging.h Mon May 20 15:47:36 2013
@@ -45,6 +45,8 @@
 	struct ao2_container *channels;
 	/*! Bridge flags to tweak behavior */
 	struct ast_flags feature_flags;
+	/*! Bridge capabilities */
+	uint32_t capabilities;
 	/*! Number of channels participating in the bridge */
 	unsigned int num_channels;
 	/*! Number of active channels in the bridge. */

Modified: team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_channels.h?view=diff&rev=389327&r1=389326&r2=389327
==============================================================================
--- team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_channels.h (original)
+++ team/kmoore/bridge_construction-cel_channels/include/asterisk/stasis_channels.h Mon May 20 15:47:36 2013
@@ -50,8 +50,6 @@
 		AST_STRING_FIELD(data);			/*!< Data passed to current application */
 		AST_STRING_FIELD(context);		/*!< Dialplan: Current extension context */
 		AST_STRING_FIELD(exten);		/*!< Dialplan: Current extension number */
-		AST_STRING_FIELD(bridged_name);		/*!< The name of the channel bridged to this one */
-		AST_STRING_FIELD(bridged_id);		/*!< The uniqueid of the channel bridged to this one */
 		AST_STRING_FIELD(caller_name);		/*!< Caller ID Name */
 		AST_STRING_FIELD(caller_number);	/*!< Caller ID Number */
 		AST_STRING_FIELD(caller_ani);		/*!< Caller ID ANI Number */
@@ -129,6 +127,18 @@
 
 /*!
  * \since 12
+ * \since 12
+ * \brief Get the most recent snapshot for channel with the given \a uniqueid.
+ *
+ * \param uniqueid Uniqueid of the snapshot to fetch.
+ * \return Most recent channel snapshot
+ * \return \c NULL on error
+ */
+struct ast_channel_snapshot *ast_channel_snapshot_get_latest(
+	const char *uniqueid);
+
+/*!
+ * \since 12
  * \brief Creates a \ref ast_channel_blob message.
  *
  * The given \a blob should be treated as immutable and not modified after it is

Modified: team/kmoore/bridge_construction-cel_channels/main/cel.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/bridge_construction-cel_channels/main/cel.c?view=diff&rev=389327&r1=389326&r2=389327
==============================================================================
--- team/kmoore/bridge_construction-cel_channels/main/cel.c (original)
+++ team/kmoore/bridge_construction-cel_channels/main/cel.c Mon May 20 15:47:36 2013
@@ -71,6 +71,12 @@
 
 /*! Subscription for forwarding the channel caching topic */
 static struct stasis_subscription *cel_bridge_forwarder;
+
+/*! Container for primary channel/bridge ID listing for 2 party bridges */
+static struct ao2_container *bridge_primaries;
+
+/*! The number of buckets into which primary channel uniqueids will be hashed */
+#define BRIDGE_PRIMARY_BUCKETS 251
 
 /*! Container for dial end multichannel blobs for holding on to dial statuses */
 static struct ao2_container *cel_dialstatus_store;
@@ -156,6 +162,75 @@
 	[AST_CEL_LINKEDID_END]     = "LINKEDID_END",
 };
 
+struct bridge_assoc {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(channel_id);	/*!< UniqueID of the primary/dialing channel */
+		AST_STRING_FIELD(bridge_id);	/*!< UniqueID of the bridge */
+		AST_STRING_FIELD(secondary_id);	/*!< UniqueID of the secondary/dialed channel */
+	);
+};
+
+static void bridge_assoc_dtor(void *obj)
+{
+	struct bridge_assoc *assoc = obj;
+	ast_string_field_free_memory(assoc);
+}
+
+static struct bridge_assoc *bridge_assoc_alloc(const char *channel_id, const char *bridge_id, const char *secondary_id)
+{
+	RAII_VAR(struct bridge_assoc *, assoc, ao2_alloc(sizeof(*assoc), bridge_assoc_dtor), ao2_cleanup);
+	if (!assoc || ast_string_field_init(assoc, 64)) {
+		return NULL;
+	}
+
+	ast_string_field_set(assoc, channel_id, channel_id);
+	ast_string_field_set(assoc, bridge_id, bridge_id);
+	ast_string_field_set(assoc, secondary_id, secondary_id);
+
+	ao2_ref(assoc, +1);
+	return assoc;
+}
+
+static int add_bridge_primary(const char *channel_id, const char *bridge_id, const char *secondary_id)
+{
+	RAII_VAR(struct bridge_assoc *, assoc, bridge_assoc_alloc(channel_id, bridge_id, secondary_id), ao2_cleanup);
+	if (!assoc) {
+		return -1;
+	}
+
+	ao2_link(bridge_primaries, assoc);
+	return 0;
+}
+
+static void remove_bridge_primary(const char *channel_id)
+{
+	ao2_find(bridge_primaries, channel_id, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK);
+}
+
+/*! \brief Hashing function for bridge_assoc */
+static int bridge_assoc_hash(const void *obj, int flags)
+{
+	const struct bridge_assoc *assoc = obj;
+	const char *uniqueid = obj;
+	if (!(flags & OBJ_KEY)) {
+		uniqueid = assoc->channel_id;
+	}
+
+	return ast_str_hash(uniqueid);
+}
+
+/*! \brief Comparator function for bridge_assoc */
+static int bridge_assoc_cmp(void *obj, void *arg, int flags)
+{
+	struct bridge_assoc *assoc1 = obj, *assoc2 = arg;
+	const char *assoc2_id = arg, *assoc1_id = assoc1->channel_id;
+	if (!(flags & OBJ_KEY)) {
+		assoc2_id = assoc2->channel_id;
+	}
+
+	return !strcmp(assoc1_id, assoc2_id) ? CMP_MATCH | CMP_STOP : 0;
+}
+
 static const char *get_caller_uniqueid(struct ast_multi_channel_blob *blob)
 {
 	struct ast_channel_snapshot *caller = ast_multi_channel_blob_get_channel(blob, "caller");
@@ -429,9 +504,20 @@
 	struct timeval eventtime;
 	struct ast_event *ev;
 	char *linkedid = ast_strdupa(snapshot->linkedid);
+	char *peer_name = "";
+	RAII_VAR(struct bridge_assoc *, assoc, NULL, ao2_cleanup);
 
 	if (!cel_enabled) {
 		return 0;
+	}
+
+	assoc = ao2_find(bridge_primaries, snapshot->uniqueid, OBJ_KEY);
+	if (assoc) {
+		RAII_VAR(struct ast_channel_snapshot *, bridged_snapshot, NULL, ao2_cleanup);
+		bridged_snapshot = ast_channel_snapshot_get_latest(assoc->secondary_id);
+		if (bridged_snapshot) {
+			peer_name = ast_strdupa(bridged_snapshot->name);
+		}
 	}
 
 	/* Make sure a reload is not occurring while we're checking to see if this
@@ -488,7 +574,7 @@
 		AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->linkedid,
 		AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->userfield,
 		AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, S_OR(extra, ""),
-		AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, snapshot->bridged_name,
+		AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peer_name,
 		AST_EVENT_IE_END);
 
 	if (ev && ast_event_queue(ev)) {
@@ -956,6 +1042,71 @@
 	}
 }
 
+static void cel_bridge_enter_cb(
+	void *data, struct stasis_subscription *sub,
+	struct stasis_topic *topic,
+	struct stasis_message *message)
+{
+	struct ast_bridge_blob *blob = stasis_message_data(message);
+	struct ast_bridge_snapshot *snapshot = blob->bridge;
+	struct ast_channel_snapshot *chan_snapshot = blob->channel;
+
+	if (snapshot->capabilities | AST_BRIDGE_CAPABILITY_1TO1MIX || snapshot->capabilities | AST_BRIDGE_CAPABILITY_NATIVE) {
+		if (ao2_container_count(snapshot->channels) == 2) {
+			struct ao2_iterator i;
+			RAII_VAR(char *, channel_id, NULL, ao2_cleanup);
+
+			/* get the name of the channel in the container we don't already know the name of */
+			i = ao2_iterator_init(snapshot->channels, 0);
+			while ((channel_id = ao2_iterator_next(&i))) {
+				if (strcmp(channel_id, chan_snapshot->uniqueid)) {
+					break;
+				}
+				ao2_cleanup(channel_id);
+				channel_id = NULL;
+			}
+			ao2_iterator_destroy(&i);
+
+			add_bridge_primary(channel_id, snapshot->uniqueid, chan_snapshot->uniqueid);
+		}
+	}
+}
+
+static void cel_bridge_leave_cb(
+	void *data, struct stasis_subscription *sub,
+	struct stasis_topic *topic,
+	struct stasis_message *message)
+{
+	struct ast_bridge_blob *blob = stasis_message_data(message);
+	struct ast_bridge_snapshot *snapshot = blob->bridge;
+	struct ast_channel_snapshot *chan_snapshot = blob->channel;
+
+	if ((snapshot->capabilities | AST_BRIDGE_CAPABILITY_1TO1MIX)
+		|| (snapshot->capabilities | AST_BRIDGE_CAPABILITY_NATIVE)) {
+		if (ao2_container_count(snapshot->channels) == 1) {
+			RAII_VAR(char *, ao2_primary, ao2_find(bridge_primaries, chan_snapshot->uniqueid, OBJ_KEY), ao2_cleanup);
+			RAII_VAR(char *, channel_id_in_bridge, NULL, ao2_cleanup);
+			char *primary;
+			struct ao2_iterator i;
+
+			/* get the only item in the container */
+			i = ao2_iterator_init(snapshot->channels, 0);
+			while ((channel_id_in_bridge = ao2_iterator_next(&i))) {
+				break;
+			}
+			ao2_iterator_destroy(&i);
+
+			if (ao2_primary) {
+				primary = ao2_primary;
+			} else {
+				primary = channel_id_in_bridge;
+			}
+
+			remove_bridge_primary(primary);
+		}
+	}
+}
+
 static void save_dialstatus(struct ast_multi_channel_blob *blob)
 {
 	ao2_link(cel_dialstatus_store, blob);
@@ -993,6 +1144,8 @@
 	ast_cli_unregister(&cli_status);
 	stasis_message_router_unsubscribe(cel_state_router);
 	cel_state_router = NULL;
+	ao2_cleanup(bridge_primaries);
+	bridge_primaries = NULL;
 }
 
 int ast_cel_engine_init(void)
@@ -1056,6 +1209,29 @@
 		return -1;
 	}
 
+	bridge_primaries = ao2_container_alloc(BRIDGE_PRIMARY_BUCKETS, bridge_assoc_hash, bridge_assoc_cmp);
+	if (!bridge_primaries) {
+		return -1;
+	}
+
+	ret |= stasis_message_router_add(cel_state_router,
+		ast_channel_entered_bridge_type(),
+		cel_bridge_enter_cb,
+		NULL);
+
+	ret |= stasis_message_router_add(cel_state_router,
+		ast_channel_left_bridge_type(),
+		cel_bridge_leave_cb,
+		NULL);
+
+	/* If somehow we failed to add any routes, just shut down the whole
+	 * thing and fail it.
+	 */
+	if (ret) {
+		ast_cel_engine_term();
+		return -1;
+	}
+
 	ast_register_atexit(ast_cel_engine_term);
 
 	return 0;

Modified: team/kmoore/bridge_construction-cel_channels/main/stasis_bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/bridge_construction-cel_channels/main/stasis_bridging.c?view=diff&rev=389327&r1=389326&r2=389327
==============================================================================
--- team/kmoore/bridge_construction-cel_channels/main/stasis_bridging.c (original)
+++ team/kmoore/bridge_construction-cel_channels/main/stasis_bridging.c Mon May 20 15:47:36 2013
@@ -94,6 +94,7 @@
 	ast_string_field_set(snapshot, technology, bridge->technology->name);
 
 	snapshot->feature_flags = bridge->feature_flags;
+	snapshot->capabilities = bridge->technology->capabilities;
 	snapshot->num_channels = bridge->num_channels;
 	snapshot->num_active = bridge->num_active;
 

Modified: team/kmoore/bridge_construction-cel_channels/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/bridge_construction-cel_channels/main/stasis_channels.c?view=diff&rev=389327&r1=389326&r2=389327
==============================================================================
--- team/kmoore/bridge_construction-cel_channels/main/stasis_channels.c (original)
+++ team/kmoore/bridge_construction-cel_channels/main/stasis_channels.c Mon May 20 15:47:36 2013
@@ -103,7 +103,6 @@
 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
 {
 	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
-	struct ast_channel *bridged;
 
 	snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor);
 	if (!snapshot || ast_string_field_init(snapshot, 1024)) {
@@ -127,17 +126,6 @@
 	ast_string_field_set(snapshot, context, ast_channel_context(chan));
 	ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
 
-	bridged = ast_bridged_channel(chan);
-	if (bridged) {
-		ast_channel_ref(bridged);
-		ast_channel_lock(bridged);
-		ast_string_field_set(snapshot, bridged_name, ast_channel_name(bridged));
-		ast_string_field_set(snapshot, bridged_id, ast_channel_uniqueid(bridged));
-		ast_channel_unlock(bridged);
-		ast_channel_unref(bridged);
-		bridged = NULL;
-	}
-
 	ast_string_field_set(snapshot, caller_name,
 		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
 	ast_string_field_set(snapshot, caller_number,
@@ -164,6 +152,28 @@
 	snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
 
 	snapshot->manager_vars = ast_channel_get_manager_vars(chan);
+
+	ao2_ref(snapshot, +1);
+	return snapshot;
+}
+
+struct ast_channel_snapshot *ast_channel_snapshot_get_latest(
+	const char *uniqueid)
+{
+        RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+	struct ast_channel_snapshot *snapshot;
+
+	msg = stasis_cache_get(ast_channel_topic_all_cached(),
+		ast_channel_snapshot_type(), uniqueid);
+
+	if (!msg) {
+		return NULL;
+	}
+
+	snapshot = stasis_message_data(msg);
+	if (!snapshot) {
+		return NULL;
+	}
 
 	ao2_ref(snapshot, +1);
 	return snapshot;




More information about the asterisk-commits mailing list