[asterisk-commits] mmichelson: branch group/CCSS r226971 - in /team/group/CCSS: include/asterisk...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Nov 2 14:48:53 CST 2009


Author: mmichelson
Date: Mon Nov  2 14:48:50 2009
New Revision: 226971

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=226971
Log:
Remove ast_cc_get_recall_core_id and replace with ast_cc_is_recall.

The reason for this is that the typical use case for this is when
a channel is called, the channel driver will wish to know if the
call to this channel is a recall or not.

This new function works by checking to see if the channel in question
exists in the list of originally-called channels and that it is
being called from the same extension and context as it was originally.
If not, then this channel has perhaps been added to the CC_INTERFACES
channel variable by the admin, or the call has been routed to a completely
different device for whatever reason.

The functionality isn't perfect yet, however. For instance, if Dial is
called twice, the second time that Dial is called, the ast_cc_is_recall
function will still return non-zero. This last portion will be taken
care of in the next commit.


Modified:
    team/group/CCSS/include/asterisk/ccss.h
    team/group/CCSS/main/ccss.c

Modified: team/group/CCSS/include/asterisk/ccss.h
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/include/asterisk/ccss.h?view=diff&rev=226971&r1=226970&r2=226971
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Mon Nov  2 14:48:50 2009
@@ -1032,13 +1032,30 @@
 
 /*!
  * \since 1.6.4
- * \brief Get the core id from the cc_recall datastore
- *
- * \param chan The channel the datastore may be on
- * \retval -1 Datastore could not be found
- * \retval non-negative core_id found on the datastore
- */
-int ast_cc_get_recall_core_id(struct ast_channel *chan);
+ * \brief Decide if a call to a particular channel is a CC recall
+ *
+ * When a CC recall happens, it is important on the called side to
+ * know that the call is a CC recall and not a normal call. This function
+ * will determine first if the call in question is a CC recall. Then it
+ * will determine based on the chan parameter if the channel is being
+ * called is being recalled.
+ *
+ * As a quick example, let's say a call is placed to SIP/1000 and SIP/1000
+ * is currently on the phone. The caller requests CCBS. SIP/1000 finishes
+ * his call, and so the caller attempts to recall. Now, the dialplan
+ * administrator has set up this second call so that not only is SIP/1000
+ * called, but also SIP/2000 is called. If SIP/1000's channel were passed
+ * to this function, the return value would be non-zero, but if SIP/2000's
+ * channel were passed into this function, then the return would be 0 since
+ * SIP/2000 was not one of the original devices dialed.
+ *
+ * \param chan A called channel
+ * \param core_id[out] If this is a valid CC recall, the core_id of the failed call
+ * will be placed in this output parameter
+ * \retval 0 Either this is not a recall or it is but this channel is not part of the recall
+ * \retval non-zero This is a recall and the channel in question is directly involved.
+ */
+int ast_cc_is_recall(struct ast_channel *chan, int *core_id);
 
 /*!
  * \since 1.6.4

Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=226971&r1=226970&r2=226971
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Mon Nov  2 14:48:50 2009
@@ -2848,22 +2848,60 @@
 	return 0;
 }
 
-int ast_cc_get_recall_core_id(struct ast_channel *chan)
+int ast_cc_is_recall(struct ast_channel *chan, int *core_id)
 {
 	struct ast_datastore *recall_datastore;
 	struct cc_recall_ds_data *recall_data;
-	int core_id_return;
+	struct ast_cc_interface_tree *interface_tree;
+	char device_name[AST_CHANNEL_NAME];
+	struct cc_tree_item *exten_tree_item;
+	struct ast_str *extencontext = ast_str_alloca(128);
+
+	ast_assert(core_id != NULL);
+
+	*core_id = -1;
 
 	ast_channel_lock(chan);
 	if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
+		/* Obviously not a recall if the datastore isn't present */
 		ast_channel_unlock(chan);
-		return -1;
+		return 0;
 	}
 
 	recall_data = recall_datastore->data;
-	core_id_return = recall_data->core_id;
+	interface_tree = cc_ref(recall_data->interface_tree, "Bump refcount for tree while we search for specific channel");
+	ast_channel_get_device_name(chan, device_name, sizeof(device_name));
+	ast_str_set(&extencontext, 0, "%s@%s", S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context));
 	ast_channel_unlock(chan);
-	return core_id_return;
+
+	/* Now we need to find out if the channel in question is in the list of interfaces in the
+	 * called tree. Finding a match based on the device name is not enough here. We need to find
+	 * a match based on device name and a parent extension tree item with the same extension and
+	 * context as the channel.
+	 */
+	AST_LIST_LOCK(interface_tree);
+	AST_LIST_TRAVERSE(interface_tree, exten_tree_item, next) {
+		/* First we try to find an extension interface with the proper
+		 * exten and context.
+		 */
+		if (!strcmp(exten_tree_item->interface->name, ast_str_buffer(extencontext))) {
+			/* Found a matching extension, now see if the channel in question is one
+			 * of its children
+			 */
+			struct cc_tree_item *device_tree_item = exten_tree_item;
+			while ((device_tree_item = AST_LIST_NEXT(device_tree_item, next))) {
+				if ((device_tree_item->parent_id == exten_tree_item->id) &&
+						!strcmp(device_tree_item->interface->name, device_name)) {
+					/* BOOM! Device is in the tree! We have a winner! */
+					*core_id = recall_data->core_id;
+					AST_LIST_UNLOCK(interface_tree);
+					return 1;
+				}
+			}
+		}
+	}
+	AST_LIST_UNLOCK(interface_tree);
+	return 0;
 }
 
 int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char * const extension)




More information about the asterisk-commits mailing list