[svn-commits] mmichelson: branch group/CCSS r226604 - in /team/group/CCSS: apps/ include/as...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Oct 29 15:41:30 CDT 2009


Author: mmichelson
Date: Thu Oct 29 15:41:26 2009
New Revision: 226604

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=226604
Log:
Change the model by which core instances are created.

It used to be that all outbound devices were collected
together and then a core instance was created after the
call had either been answered or hung up.

Since ISDN requires that the calling channel driver be
made aware of the ability to offer CC prior to sending
the ALERTING message or DISCONNECT message, it is necessary
to have the agent created for the caller as soon as possible.
Now we create a core instance and an agent as soon as we
read the first CC control frame.

This change touches quite a few areas in addition to
what was mentioned above.

1. ast_cc_core_init_instance is now a private function
called cc_core_init_instance.
2. ast_cc_create_new_core has been removed since there
is no reason for anything outside of ccss to request for
a CC core to be created.
3. cc_core_init_instance now returns a reference to a
core instance instead of the core_id of the newly
created core_instance.


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://svnview.digium.com/svn/asterisk/team/group/CCSS/apps/app_dial.c?view=diff&rev=226604&r1=226603&r2=226604
==============================================================================
--- team/group/CCSS/apps/app_dial.c (original)
+++ team/group/CCSS/apps/app_dial.c Thu Oct 29 15:41:26 2009
@@ -944,7 +944,6 @@
 				ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
 			}
 			*to = 0;
-			ast_cc_create_new_core(in);
 			return NULL;
 		}
 		winner = ast_waitfor_n(watchers, pos, to);
@@ -1241,7 +1240,6 @@
 					}
 					ast_frfree(f);
 				}
-				ast_cc_create_new_core(in);
 				return NULL;
 			}
 
@@ -1259,7 +1257,6 @@
 						strcpy(pa->status, "CANCEL");
 						ast_frfree(f);
 						ast_channel_unlock(in);
-						ast_cc_create_new_core(in);
 						return NULL;
 					}
 					ast_channel_unlock(in);
@@ -1272,7 +1269,6 @@
 					strcpy(pa->status, "CANCEL");
 					ast_cdr_noanswer(in->cdr);
 					ast_frfree(f);
-					ast_cc_create_new_core(in);
 					return NULL;
 				}
 			}
@@ -1315,7 +1311,6 @@
 	}
 #endif
 
-	ast_cc_create_new_core(in);
 	return peer;
 }
 

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=226604&r1=226603&r2=226604
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Thu Oct 29 15:41:26 2009
@@ -599,23 +599,6 @@
 /*!
  * \since 1.6.4
  *
- * \brief Create a new core instance
- *
- * CC-capable applications, such as Dial, will call this function
- * after it is known that all interfaces which may have possibly
- * offered CC to the caller have done so. This function will start
- * the process of creating a new instance of the CC core to be used
- * for this CC transaction.
- *
- * \param inbound The inbound channel which has called the CC-capable application
- * \retval 0 Success
- * \retval -1 Failure
- */
-int ast_cc_create_new_core(struct ast_channel *inbound);
-
-/*!
- * \since 1.6.4
- *
  * \brief Start the CC process on a call.
  *
  * Whenever a CC-capable application, such as Dial, wishes to
@@ -883,31 +866,6 @@
 
 /*!
  * \since 1.6.4
- * \brief Allocate and initialize an instance of the CCSS core
- *
- * This function takes as arguments the caller's channel and the
- * current list of called interfaces that app_dial has created. Note
- * that after this function is called, it is perfectly acceptable
- * for app_dial to continue adding interfaces to the called_tree.
- *
- * This function currently will add the called tree to a container
- * of pending CC offers, so that they may be saved for future use.
- *
- * XXX There is no reason for this to be public. It was made this way
- * because initially it was called directly by app_dial, but now it
- * is only called by ast_cc_create_new_core.
- *
- * \param caller The caller's channel
- * \param called_tree A tree indicating the interfaces dialed during
- * this call, as well as which type of call completion service should
- * be requested for each device
- * \retval negative The CCSS core failed to be initialized.
- * \retval non-negative The identifier for this instance of the CCSS core
- */
-int ast_cc_core_init_instance(struct ast_channel *caller, struct ast_cc_interface_tree *called_tree);
-
-/*!
- * \since 1.6.4
  * \brief Offer CC to a caller
  *
  * This function is called from ast_hangup if the caller is

Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=226604&r1=226603&r2=226604
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Thu Oct 29 15:41:26 2009
@@ -124,6 +124,27 @@
  */
 static int cc_request_state_change(enum cc_state, int core_id, const char * debug);
 
+/*!
+ * \brief create a new instance of the CC core and an agent for the calling channel
+ *
+ * This function will check to make sure that the incoming channel
+ * is allowed to request CC by making sure that the incoming channel
+ * has not exceeded its maximum number of allowed agents.
+ *
+ * Should that check pass, the core instance is created, and then the
+ * agent for the channel.
+ *
+ * \param caller_chan The incoming channel for this particular call
+ * \param called_tree A reference to the tree of called devices. The agent
+ * will gain a reference to this tree as well
+ * \param core_id The core_id that this core_instance will assume
+ * \retval NULL Failed to create the core instance either due to memory allocation
+ * errors or due to the agent count for the caller being too high
+ * \retval non-NULL A reference to the newly created cc_core_instance
+ */
+static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
+		struct ast_cc_interface_tree *called_tree, const int core_id);
+
 static const char *CC_LOGGER_LEVEL_NAME = "CC";
 static int cc_logger_level;
 
@@ -198,6 +219,13 @@
 	struct cc_core_instance *core_instance2 = arg;
 
 	return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
+}
+
+static struct cc_core_instance *find_cc_core_instance(const int core_id)
+{
+	struct cc_core_instance finder = {.core_id = core_id,};
+
+	return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance");
 }
 
 enum match_flags {
@@ -1249,11 +1277,13 @@
 	 */
 	char done;
 	/*!
-	 * When nested dials occur (i.e. dialing local channels), we need
-	 * to be sure that they will not try to create a core instance themselves.
-	 * Instead, they need to pass the frame up to the parent dialing application.
-	 */
-	char nested_dial;
+	 * When we process a CC control frame, we will create a new instance
+	 * of the CC core for the call. However, we only need to do this on 
+	 * the first CC control frame received. We set the core_created to be
+	 * non-zero so that we don't try to allocate multiple instances of the
+	 * core for a single call.
+	 */
+	char core_created;
 	/*!
 	 * When nested dials occur (i.e. dialing local channels), the invocation
 	 * of the Local channel may have modifiers like /n or /b on the channel name.
@@ -1307,7 +1337,6 @@
 	}
 	new_cc_interfaces->done = old_cc_interfaces->done;
 	new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
-	new_cc_interfaces->nested_dial = 1;
 	ao2_t_ref(old_cc_interfaces->interface_tree, +1, "New ref due to duplication of interface tree");
 	new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
 	return new_cc_interfaces;
@@ -1557,19 +1586,32 @@
 	struct ast_datastore *cc_datastore;
 	struct dialed_cc_interfaces *cc_interfaces;
 	struct ast_control_cc_payload *cc_data = frame_data;
+	struct cc_core_instance *core_instance;
 
 	ast_channel_get_device_name(outbound, device_name, sizeof(device_name));
 
+	ast_channel_lock(inbound);
 	if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
 		ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
+		ast_channel_unlock(inbound);
 		return;
 	}
 
 	cc_interfaces = cc_datastore->data;
 
 	if (cc_interfaces->done) {
+		ast_channel_unlock(inbound);
 		return;
 	}
+
+	if (!(core_instance = find_cc_core_instance(cc_interfaces->core_id)) &&
+			!(core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree, cc_interfaces->core_id))) {
+		cc_interfaces->done = 1;
+		ast_channel_unlock(inbound);
+		return;
+	}
+
+	ast_channel_unlock(inbound);
 
 	/* Yeah this kind of sucks, but luckily most people
 	 * aren't dialing thousands of interfaces on every call
@@ -1582,6 +1624,7 @@
 		if (!strcmp(tree_item->interface->name, device_name)) {
 			ast_log_dynamic_level(cc_logger_level, "Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n", device_name);
 			AST_LIST_UNLOCK(cc_interfaces->interface_tree);
+			cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame");
 			return;
 		}
 	}
@@ -1590,6 +1633,7 @@
 
 	if (!(tree_item = cc_device_tree_item_init(device_name, cc_interfaces->dial_parent_id, cc_data))) {
 		ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
+		cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame");
 		return;
 	}
 
@@ -1603,44 +1647,9 @@
 		"Service: %s\r\n",
 		cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service)
 	);
-}
-
-int ast_cc_create_new_core(struct ast_channel *inbound)
-{
-	struct ast_datastore *cc_datastore;
-	struct dialed_cc_interfaces *cc_interfaces;
-	int is_tree_empty;
-
-	ast_channel_lock(inbound);
-	if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
-		ast_channel_unlock(inbound);
-		return -1;
-	}
-	ast_channel_unlock(inbound);
-
-	cc_interfaces = cc_datastore->data;
-
-	if (cc_interfaces->nested_dial || cc_interfaces->done) {
-		/* Abort. Nested dials have no place trying
-		 * to create an instance of the core. Leave this
-		 * for the topmost Dial.
-		 *
-		 * Similarly, if the done field is non-zero, this means
-		 * that the channel should not be allowed to create
-		 * an instance of the core either.
-		 */
-		return 0;
-	}
-
-	AST_LIST_LOCK(cc_interfaces->interface_tree);
-	is_tree_empty = AST_LIST_EMPTY(cc_interfaces->interface_tree);
-	AST_LIST_UNLOCK(cc_interfaces->interface_tree);
-
-	if (!is_tree_empty) {
-		ast_cc_core_init_instance(inbound, cc_interfaces->interface_tree);
-		ast_set_flag(inbound, AST_FLAG_OFFER_CC);
-	}
-	return 0;
+
+	core_instance->agent->callbacks->offer_cc(core_instance->agent, device_name);
+	cc_unref(core_instance, "Done with core_instance after calling agent offer_cc callback");
 }
 
 int ast_cc_call_init(struct ast_channel *chan, int *ignore_cc)
@@ -2037,12 +2046,11 @@
 	}
 }
 
-int ast_cc_core_init_instance(struct ast_channel *caller_chan,
-		struct ast_cc_interface_tree *called_tree)
+static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
+		struct ast_cc_interface_tree *called_tree, const int core_id)
 {
 	char caller[AST_CHANNEL_NAME];
 	struct cc_core_instance *core_instance;
-	int core_id;
 	long agent_count;
 
 	ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
@@ -2054,35 +2062,30 @@
 	agent_count = count_agents(caller);
 	if (agent_count >= ast_get_cc_max_agents(ast_channel_get_cc_config_params(caller_chan))) {
 		ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
-		return -1;
+		return NULL;
 	}
 
 	/* Generic agents can only have a single outstanding CC request per caller. */
 	if (ast_get_cc_agent_policy(ast_channel_get_cc_config_params(caller_chan)) == AST_CC_AGENT_GENERIC &&
 			agent_count > 0) {
 		ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
-		return -1;
-	}
-
-	if ((core_id = ast_cc_get_current_core_id(caller_chan)) == -1) {
-		return -1;
+		return NULL;
 	}
 
 	/* Next, we need to create the core instance for this call */
 	if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
-		return -1;
+		return NULL;
 	}
 
 	core_instance->core_id = core_id;
 	if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
 		cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
-		return -1;
+		return NULL;
 	}
 
 	ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
-	cc_unref(core_instance, "Linked core instance, unref from ao2_alloc()"); /* From ao2_alloc. */
-
-	return core_instance->core_id;
+
+	return core_instance;
 }
 
 static void monitor_destroy(void *data)




More information about the svn-commits mailing list