[asterisk-commits] mmichelson: branch group/CCSS r213630 - in /team/group/CCSS: apps/ include/as...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Aug 21 15:22:43 CDT 2009
Author: mmichelson
Date: Fri Aug 21 15:22:39 2009
New Revision: 213630
URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=213630
Log:
Commit some "progress"
I say "progress" because, well, app_dial is somewhat of a mess
right now. However, what's there compiles, so that's a start.
Modified:
team/group/CCSS/apps/app_dial.c
team/group/CCSS/include/asterisk/ccss.h
team/group/CCSS/main/ccss.c
Modified: team/group/CCSS/apps/app_dial.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/CCSS/apps/app_dial.c?view=diff&rev=213630&r1=213629&r2=213630
==============================================================================
--- team/group/CCSS/apps/app_dial.c (original)
+++ team/group/CCSS/apps/app_dial.c Fri Aug 21 15:22:39 2009
@@ -1625,6 +1625,149 @@
return 1; /* success */
}
+static int dial_cc_interface_counter;
+
+/*!
+ * \brief data stored in CC datastore
+ *
+ * The datastore creates a list of interfaces that were
+ * dialed, including both extensions and devices. In addition
+ * to the intrinsic data of the tree, some extra information
+ * is needed for use by app_dial.
+ */
+struct dial_cc_interfaces {
+ /*!
+ * When a new Dial application is started, and the datastore
+ * already exists on the channel, we can figure out where
+ * in the existing interface tree to insert the new information
+ * by using this number.
+ */
+ unsigned int dial_parent_id;
+ /*!
+ * When a new Dial application is started, and the datastore
+ * already exists on the channel, we can determine if we
+ * should be adding any new interface information to tree.
+ */
+ char done;
+ /*!
+ * Reference-counted "tree" of interfaces.
+ */
+ struct ast_cc_interface_tree *interface_tree;
+};
+
+static void dial_cc_interfaces_destroy(void *data)
+{
+ struct dial_cc_interfaces *cc_interfaces = data;
+ ao2_ref(cc_interfaces->interface_tree, -1);
+ ast_free(cc_interfaces);
+}
+
+static void *dial_cc_interfaces_duplicate(void *data)
+{
+ /* STUB */
+ return NULL;
+}
+
+static const struct ast_datastore_info dial_cc_interfaces_info = {
+ .type = "Dial CC Interfaces",
+ .duplicate = dial_cc_interfaces_duplicate,
+ .destroy = dial_cc_interfaces_destroy,
+};
+
+static struct ast_cc_interface *cc_extension_interface_init(const char * const exten, const char * const context, const unsigned int parent_id)
+{
+ struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION);
+ struct ast_cc_interface *cc_interface;
+
+ ast_str_set(&str, 0, "%s@%s\n", exten, context);
+
+ if (!(cc_interface = ast_calloc(1, sizeof(*cc_interface) + ast_str_strlen(str)))) {
+ return NULL;
+ }
+
+ cc_interface->id = ast_atomic_fetchadd_int(&dial_cc_interface_counter, +1);
+ cc_interface->parent_id = parent_id;
+ strcpy(cc_interface->name, ast_str_buffer(str));
+ return cc_interface;
+}
+
+static int cc_interfaces_datastore_init(struct ast_channel *chan) {
+ struct dial_cc_interfaces *interfaces;
+ struct ast_cc_interface *cc_interface;
+ struct ast_datastore *dial_cc_datastore;
+
+ if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
+ return -1;
+ }
+
+ if (!(cc_interface = cc_extension_interface_init(chan->exten, chan->context, 1))) {
+ ast_free(interfaces);
+ return -1;
+ }
+
+ if (!(dial_cc_datastore = ast_datastore_alloc(&dial_cc_interfaces_info, NULL))) {
+ ast_free(cc_interface);
+ ast_free(interfaces);
+ return -1;
+ }
+
+ if (!(interfaces->interface_tree = ao2_alloc(sizeof(*interfaces->interface_tree), ast_cc_interface_tree_destroy))) {
+ ast_datastore_free(dial_cc_datastore);
+ ast_free(cc_interface);
+ ast_free(interfaces);
+ return -1;
+ }
+
+ /* Finally, all that allocation is done... */
+ AST_LIST_HEAD_INIT(interfaces->interface_tree);
+ AST_LIST_INSERT_TAIL(interfaces->interface_tree, cc_interface, next);
+ dial_cc_datastore->data = interfaces;
+ ast_channel_lock(chan);
+ ast_channel_datastore_add(chan, dial_cc_datastore);
+ ast_channel_unlock(chan);
+ return 0;
+}
+
+static int create_root_cc_interface(struct ast_channel *chan)
+{
+ /* All right. So here's the deal. There are three things
+ * that can happen here:
+ *
+ * 1. The channel does not have a cc_interface datastore on
+ * it. This means that this is the first time that Dial has
+ * been called. We need to create/initialize the datastore.
+ *
+ * 2. The channel does have a cc_interface datastore on it and
+ * the "done" indicator is 0. This means that a Local channel
+ * was called by a "parent" dial. We can check the datastore's
+ * parent field to see who the root of this particular dial tree
+ * is.
+ *
+ * 3. The channel does have a cc_interface datastore on it and
+ * the "done" indicator is 1. This means that a second Dial call
+ * is being made from an extension. In this case, we do not
+ * want to make any additions/modifications to the datastore. We
+ * will instead set a flag to indicate that CCSS is completely
+ * disabled for this Dial attempt.
+ */
+
+ struct ast_datastore *cc_interfaces_datastore;
+ struct dial_cc_interfaces *interfaces;
+ ast_channel_lock(chan);
+ if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dial_cc_interfaces_info, NULL))) {
+ /* Situation 1 has occurred */
+ return cc_interfaces_datastore_init(chan);
+ }
+
+ interfaces = cc_interfaces_datastore->data;
+ if (!interfaces->done) {
+ /* Situation 2 has occurred */
+ } else {
+ /* Situation 3 has occurred */
+ }
+ return 0;
+}
+
static void end_bridge_callback(void *data)
{
char buf[80];
@@ -1703,6 +1846,10 @@
return -1;
}
+ ast_log(LOG_NOTICE, "Out of curiosity, what are the channel's exten and context?\n");
+ ast_log(LOG_NOTICE, "Exten is '%s' and context is '%s'\n", chan->exten, chan->context);
+ ast_log(LOG_NOTICE, "Macroexten is '%s' and macrocontext is '%s'\n", chan->macroexten, chan->macrocontext);
+
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
@@ -1718,6 +1865,8 @@
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
goto done;
}
+
+ create_root_cc_interface(chan);
if (ast_test_flag64(&opts, OPT_OPERMODE)) {
opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
Modified: team/group/CCSS/include/asterisk/ccss.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/CCSS/include/asterisk/ccss.h?view=diff&rev=213630&r1=213629&r2=213630
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Fri Aug 21 15:22:39 2009
@@ -27,7 +27,9 @@
#include "asterisk.h"
#include "asterisk/linkedlists.h"
-enum service_type {
+enum ast_cc_service_type {
+ /* No Service available/requested */
+ AST_CC_NONE,
/* Call Completion Busy Subscriber */
AST_CC_CCBS,
/* Call Completion No Response */
@@ -348,6 +350,10 @@
* Of course the other problem is that if this is going to exist
* as a datastore on the channel, then dialing local channels should
* probably result in their increasing a reference count on the data.
+ *
+ * Actually, there really doesn't need to be a new lock for this structure.
+ * After all, since I'll be using a datastore, I'll need to lock the channel
+ * to operate on the datastore.
*/
/* So the gory datastore details will be in app_dial. However, the structure
@@ -363,6 +369,60 @@
* the list. We can guarantee that we will generally be going in a top-to-bottom
* order.
*/
+
+/* This may be a candidate for opacity. Who the heck knows. */
+struct ast_cc_interface {
+ /* Every interface has an id associated with it. Think of
+ * it like a "primary key"
+ */
+ unsigned int id;
+ /* Who is this interface's parent interface? The "root" of
+ * the tree will have 0 for this. Everyone else will have at
+ * least 1 as their parent_id.
+ */
+ unsigned int parent_id;
+ /* What service was offered by the endpoint. Note that
+ * this field is completely irrelevant for ast_cc_interfaces
+ * representing dialplan extensions.
+ */
+ enum ast_cc_service_type service_offered;
+ AST_LIST_ENTRY(ast_cc_interface) next;
+ /* The name of the interface/extension. local channels will
+ * have 'exten at context' for a name. Other channel types will
+ * have 'tech/device' for a name.
+ */
+ char name[1];
+};
+
+/*!
+ * \brief The "tree" of interfaces that is dialed.
+ *
+ * It is reference counted since several threads may need
+ * to use it, and it may last beyond the lifetime of a single
+ * thread.
+ */
+AST_LIST_HEAD(ast_cc_interface_tree, ast_cc_interface);
+
+/*!
+ * \brief Destructor function for an ast_cc_interface tree
+ *
+ * \param data The ast_cc_interface_tree whose refcount has reached 0
+ */
+void ast_cc_interface_tree_destroy(void *cc_interface_tree);
+
+/* So what APIs do we need... At least preliminarily, I'll need
+ * a debugging function so I can be sure the "tree" is built properly.
+ * Then, there will need to be a function to store the information in
+ * the CC core once app_dial has completed. Further, there should
+ * be some core internal functions to build the monitor tree (or add
+ * to the existing monitor graph as it may be) using the given list.
+ */
+
+int ast_store_cc_interface_tree(struct ast_cc_interface_tree *cc_interface_tree);
+
+int ast_add_cc_interface_to_tree(struct ast_cc_interface_tree *cc_interface_tree, struct ast_cc_interface *cc_interface);
+
+void ast_print_cc_interface_tree(struct ast_cc_interface_tree *cc_interface_tree);
/* END TREE STRUCTURES AND API FOR APP_DIAL'S USE */
@@ -424,7 +484,7 @@
/*! We need to remember which type of service to request/was requested
* by this specific device monitor so we don't cause problems downstream
*/
- enum service_type service_requested;
+ enum ast_cc_service_type service_requested;
/*! A device name, formatted in a way that is understood by ast_device_state*
* functions.
*/
Modified: team/group/CCSS/main/ccss.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=213630&r1=213629&r2=213630
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Fri Aug 21 15:22:39 2009
@@ -352,3 +352,18 @@
ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro));
}
}
+
+int ast_add_cc_interface_to_tree(struct ast_cc_interface_tree *cc_interface_tree, struct ast_cc_interface *cc_interface)
+{
+ AST_LIST_INSERT_TAIL(cc_interface_tree, cc_interface, next);
+ return 0;
+}
+
+void ast_cc_interface_tree_destroy(void *data)
+{
+ struct ast_cc_interface_tree *cc_interface_tree = data;
+ struct ast_cc_interface *cc_interface;
+ while ((cc_interface = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
+ ast_free(cc_interface);
+ }
+}
More information about the asterisk-commits
mailing list