[asterisk-commits] rmudgett: branch group/CCSS r240714 - in /team/group/CCSS: channels/ include/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jan 15 23:10:50 CST 2010


Author: rmudgett
Date: Fri Jan 15 23:10:46 2010
New Revision: 240714

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=240714
Log:
Stop monitor CC available routines from trying to figure out the monitor type.

cc_build_payload() was trying to figure out what monitor type to use based
upon the monitor policy and the channel name.  Not a good thing.  So I
made it take a monitor type parameter.  Most of the other changes are
ripple effects of this change.  In the process, I fixed a bunch of
failure conditions and added more doxygen comments.

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

Modified: team/group/CCSS/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/channels/chan_dahdi.c?view=diff&rev=240714&r1=240713&r2=240714
==============================================================================
--- team/group/CCSS/channels/chan_dahdi.c (original)
+++ team/group/CCSS/channels/chan_dahdi.c Fri Jan 15 23:10:46 2010
@@ -7962,7 +7962,7 @@
 	return f;
 }
 
-static int dahdi_cc_is_possible(struct ast_channel *chan, const char * const device_name)
+static const char *dahdi_cc_is_possible(struct ast_channel *chan, const char * const device_name)
 {
 	struct ast_cc_config_params *cc_params = ast_channel_get_cc_config_params(chan);
 	enum ast_cc_monitor_policies monitor_policy = ast_get_cc_monitor_policy(cc_params);
@@ -7973,14 +7973,14 @@
 	} else if (monitor_policy == AST_CC_MONITOR_NATIVE) {
 		monitor_type = "DAHDI";
 	} else {
-		return 0;
+		return NULL;
 	}
 
 	if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
-		return 0;
-	}
-
-	return 1;
+		return NULL;
+	}
+
+	return monitor_type;
 }
 
 static struct ast_frame *dahdi_read(struct ast_channel *ast)
@@ -8059,24 +8059,24 @@
 	if (p->subs[idx].needringing) {
 		if (!p->subs[idx].ccframesent) {
 			char device_name[256];
+			const char *monitor_type;
+
 			ast_channel_get_device_name(p->owner, device_name, sizeof(device_name));
-			if (dahdi_cc_is_possible(p->owner, device_name)) {
-				/* XXX I'm going to need an indication that I've sent a CC frame so I don't
-				 * just keep sending them forever
-				 */
-				if (!ast_cc_build_frame(p->owner, p->cc_params, device_name, p->dialstring, AST_CC_CCNR, &p->subs[idx].f)) {
-					p->subs[idx].needringing = 0;
-					return &p->subs[idx].f;
-				}
-			}
-			/* Even if we didn't really send a CC frame, we need to set this
+			monitor_type = dahdi_cc_is_possible(p->owner, device_name);
+			if (monitor_type
+				&& !ast_cc_build_frame(p->owner, p->cc_params, monitor_type, device_name, p->dialstring, AST_CC_CCNR, &p->subs[idx].f)) {
+				p->subs[idx].ccframesent = 1;
+				return &p->subs[idx].f;
+			}
+			/*
+			 * If CC isn't possible or if we can't build the CC frame properly,
+			 * then we drop into the typical behavior instead.
+			 *
+			 * Even if we didn't really send a CC frame, we need to set this
 			 * true so that we don't repeatedly attempt to send them and never
 			 * send a ringing frame.
 			 */
 			p->subs[idx].ccframesent = 1;
-			/* If CC isn't possible or if we can't build the CC frame properly,
-			 * then we drop into the typical behavior instead
-			 */
 		}
 		/* Send ringing frame if requested */
 		p->subs[idx].needringing = 0;
@@ -12321,6 +12321,21 @@
 	return tmp;
 }
 
+/*!
+ * \brief Callback made when dial failed to get a channel out of dahdi_request().
+ * \since 1.8
+ *
+ * \param inbound Incoming asterisk channel.
+ * \param dest Same dial string passed to dahdi_request().
+ * \param callback Callback into CC core to announce a busy channel available for CC.
+ *
+ * \details
+ * This callback acts like a forked dial with all prongs of the fork busy.
+ * Essentially, for each channel that could have taken the call, indicate that
+ * it is busy.
+ *
+ * \return Nothing
+ */
 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 {
 	struct dahdi_pvt *p, *exitpvt;
@@ -12337,25 +12352,53 @@
 	for (;;) {
 		if (is_group_or_channel_match(p, groupmatch, &groupmatched, channelmatch, &channelmatched)) {
 			/* We found a potential match. call the callback */
-			struct ast_str *interface_name;
+			struct ast_str *device_name;
+			char *dash;
+			const char *monitor_type;
 			char dialstring[AST_CHANNEL_NAME];
-			char full_interface_name[AST_CHANNEL_NAME];
+			char full_device_name[AST_CHANNEL_NAME];
+
+			switch (ast_get_cc_monitor_policy(p->cc_params)) {
+			case AST_CC_MONITOR_NEVER:
+				break;
+			case AST_CC_MONITOR_NATIVE:
+			case AST_CC_MONITOR_ALWAYS:
+			case AST_CC_MONITOR_GENERIC:
 #if defined(HAVE_PRI)
-			char address[AST_CHANNEL_NAME];
-
-			if (dahdi_sig_pri_lib_handles(p->sig)) {
-				sig_pri_extract_called_num_subaddr(p->sig_pvt, dest, address, sizeof(address));
-			} else {
-				address[0] = '\0';
-			}
-			interface_name = create_channel_name(p, 1, address);
+				if (dahdi_sig_pri_lib_handles(p->sig)) {
+					char address[AST_CHANNEL_NAME];
+	
+					sig_pri_extract_called_num_subaddr(p->sig_pvt, dest, address, sizeof(address));
+					device_name = create_channel_name(p, 1, address);
+				} else {
+					device_name = create_channel_name(p, 1, "");
+				}
 #else
-			interface_name = create_channel_name(p);
+				device_name = create_channel_name(p);
 #endif	/* defined(HAVE_PRI) */
-			snprintf(full_interface_name, sizeof(full_interface_name), "DAHDI/%s", ast_str_buffer(interface_name));
-			snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
-			callback(inbound, p->cc_params, full_interface_name, dialstring);
-			ast_free(interface_name);
+				snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", ast_str_buffer(device_name));
+				ast_free(device_name);
+				/*
+				 * The portion after the '-' in the channel name is either a random
+				 * number, a sequence number, or a subchannel number. None are
+				 * necessary so strip them off.
+				 */
+				dash = strrchr(full_device_name, '-');
+				if (dash) {
+					*dash = '\0';
+				}
+				snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
+
+				/*
+				 * Analog can only do generic monitoring.
+				 * ISDN is in a trunk busy condition and any "device" is going
+				 * to be busy until a B channel becomes available.  The generic
+				 * monitor can be made to do this task.
+				 */
+				monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
+				callback(inbound, p->cc_params, monitor_type, full_device_name, dialstring);
+				break;
+			}
 		}
 		p = backwards ? p->prev : p->next;
 		if (!p) {

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=240714&r1=240713&r2=240714
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Fri Jan 15 23:10:46 2010
@@ -1435,6 +1435,12 @@
  * \since 1.8
  * \brief Callback made from ast_cc_callback for certain channel types
  *
+ * \param inbound Incoming asterisk channel.
+ * \param cc_params The CC configuration parameters for the outbound target
+ * \param monitor_type The type of monitor to use when CC is requested
+ * \param device_name The name of the outbound target device.
+ * \param dialable_name The dial string used when calling this specific interface
+ *
  * \details
  * For channel types that fail ast_request when the device is busy, we call into the
  * channel driver with ast_cc_callback. This is the callback that is called in that
@@ -1446,7 +1452,7 @@
  * by the channel driver.
  */
 void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
-		const char * const interface_name, const char * const dialable_name);
+	const char *monitor_type, const char * const device_name, const char * const dialable_name);
 
 /*!
  * \since 1.8
@@ -1460,7 +1466,8 @@
  *
  * \param chan A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided
  * \param cc_params The CC configuration parameters for the outbound target
- * \param interface_name The name of the outbound target
+ * \param monitor_type The type of monitor to use when CC is requested
+ * \param device_name The name of the outbound target device.
  * \param dialable_name The dial string used when calling this specific interface
  * \param service What kind of CC service is being offered. (CCBS/CCNR/etc...)
  * \param[out] frame. The frame we will be returning to the caller. It is vital that ast_frame_free be called on this frame since the
@@ -1469,11 +1476,29 @@
  * \retval 0 Success
  */
 int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
-		const char * const interface_name, const char * const dialable_name, enum ast_cc_service_type service,
-		struct ast_frame *frame);
-
+	const char *monitor_type, const char * const device_name,
+	const char * const dialable_name, enum ast_cc_service_type service, struct ast_frame *frame);
+
+
+/*!
+ * \brief Callback made from ast_cc_callback for certain channel types
+ * \since 1.8
+ *
+ * \param chan A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided
+ * \param cc_params The CC configuration parameters for the outbound target
+ * \param monitor_type The type of monitor to use when CC is requested
+ * \param device_name The name of the outbound target device.
+ * \param dialable_name The dial string used when calling this specific interface
+ *
+ * \details
+ * For channel types that fail ast_request when the device is busy, we call into the
+ * channel driver with ast_cc_callback. This is the callback that is called in that
+ * case for each device found which could have been returned by ast_request.
+ *
+ * \return Nothing
+ */
 typedef void (*ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
-		const char * const interface_name, const char * const dialable_name);
+	const char *monitor_type, const char * const device_name, const char * const dialable_name);
 
 /*!
  * \since 1.8

Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=240714&r1=240713&r2=240714
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Fri Jan 15 23:10:46 2010
@@ -1555,8 +1555,18 @@
 }
 
 struct ast_control_cc_payload {
+	/*!
+	 * \note This really should be an array of characters in case this payload
+	 * is sent accross an IAX2 link.  However, this would not make too much sense
+	 * given this type may not be recognized by the other end.
+	 * Protection may be necessary to prevent it from being transmitted.
+	 *
+	 * In addition the following other problems are also possible:
+	 * 1) Endian issues with the integers/enums stored in the config_params.
+	 * 2) Alignment padding issues for the element types.
+	 */
+	const char *monitor_type;
 	enum ast_cc_service_type service;
-	const char *monitor_type;
 	struct ast_cc_config_params config_params;
 	int parent_interface_id;
 	char device_name[AST_CHANNEL_NAME];
@@ -3318,48 +3328,28 @@
 }
 
 static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
-		const char * const interface_name, const char * dialable_name,
-		enum ast_cc_service_type service, struct ast_control_cc_payload *payload)
+	const char *monitor_type, const char * const device_name, const char * dialable_name,
+	enum ast_cc_service_type service, struct ast_control_cc_payload *payload)
 {
 	struct ast_datastore *datastore;
 	struct dialed_cc_interfaces *cc_interfaces;
-	enum ast_cc_monitor_policies monitor_policy = ast_get_cc_monitor_policy(cc_params);
-	const char *interface_name_copy = ast_strdupa(interface_name);
 	int dial_parent_id;
 
 	ast_channel_lock(chan);
-	if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
+	datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL);
+	if (!datastore) {
 		ast_channel_unlock(chan);
 		return -1;
 	}
-
 	cc_interfaces = datastore->data;
 	dial_parent_id = cc_interfaces->dial_parent_id;
 	ast_channel_unlock(chan);
 
+	payload->monitor_type = monitor_type;
 	payload->service = service;
-	if (monitor_policy == AST_CC_MONITOR_GENERIC || monitor_policy == AST_CC_MONITOR_ALWAYS) {
-		payload->monitor_type = "generic";
-	} else if (monitor_policy == AST_CC_MONITOR_NATIVE) {
-		char *slash = strchr(interface_name_copy, '/');
-		const struct ast_cc_monitor_callbacks *callbacks;
-		if (!slash) {
-			ast_log_dynamic_level(cc_logger_level, "Unable to determine proper CC monitor type.\n");
-			return -1;
-		}
-		*slash = '\0';
-		if (!(callbacks = find_monitor_callbacks(interface_name_copy))) {
-			ast_log_dynamic_level(cc_logger_level, "No monitor type corresponds to %s\n", interface_name_copy);
-			return -1;
-		}
-		payload->monitor_type = callbacks->type;
-	} else { /* AST_CC_MONITOR_NEVER */
-		ast_log_dynamic_level(cc_logger_level, "Interface %s does not allow CC\n", interface_name);
-		return -1;
-	}
 	ast_cc_copy_config_params(&payload->config_params, cc_params);
 	payload->parent_interface_id = dial_parent_id;
-	ast_copy_string(payload->device_name, interface_name, sizeof(payload->device_name));
+	ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
 	ast_copy_string(payload->dialable_name, dialable_name, sizeof(payload->dialable_name));
 	return 0;
 }
@@ -3368,17 +3358,21 @@
 		const char * const dialable_name, enum ast_cc_service_type service)
 {
 	struct ast_frame frame = {0,};
-	char chan_name[AST_CHANNEL_NAME];
+	char device_name[AST_CHANNEL_NAME];
 	int retval;
-
-	ast_channel_get_device_name(chan, chan_name, sizeof(chan_name));
-
-	if (ast_cc_monitor_count(chan_name, monitor_type) >= ast_get_cc_max_monitors(ast_channel_get_cc_config_params(chan))) {
-		ast_log(LOG_NOTICE, "Not queuing a CC frame for channel %s since it already has its maximum monitors allocated\n", chan_name);
-		return -1;
-	}
-
-	if (ast_cc_build_frame(chan, ast_channel_get_cc_config_params(chan), chan_name, dialable_name, service, &frame)) {
+	struct ast_cc_config_params *cc_params;
+
+	cc_params = ast_channel_get_cc_config_params(chan);
+	if (!cc_params) {
+		return -1;
+	}
+	ast_channel_get_device_name(chan, device_name, sizeof(device_name));
+	if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
+		ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
+		return -1;
+	}
+
+	if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialable_name, service, &frame)) {
 		/* Frame building failed. We can't use this. */
 		return -1;
 	}
@@ -3387,11 +3381,16 @@
 	return retval;
 }
 
-int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char * const interface_name,
-		const char * const dialable_name, enum ast_cc_service_type service, struct ast_frame *frame)
+int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
+	const char *monitor_type, const char * const device_name,
+	const char * const dialable_name, enum ast_cc_service_type service, struct ast_frame *frame)
 {
 	struct ast_control_cc_payload *payload = ast_calloc(1, sizeof(*payload));
-	if (cc_build_payload(chan, cc_params, interface_name, dialable_name, service, payload)) {
+
+	if (!payload) {
+		return -1;
+	}
+	if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialable_name, service, payload)) {
 		/* Something screwed up, we can't make a frame with this */
 		ast_free(payload);
 		return -1;
@@ -3408,6 +3407,8 @@
 {
 	char device_name[AST_CHANNEL_NAME];
 	struct ast_control_cc_payload payload;
+	struct ast_cc_config_params *cc_params;
+
 	if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) {
 		/* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
 		 * failing is something other than busy or congestion
@@ -3415,7 +3416,11 @@
 		return;
 	}
 
-	if (ast_get_cc_monitor_policy(ast_channel_get_cc_config_params(outgoing)) != AST_CC_MONITOR_GENERIC) {
+	cc_params = ast_channel_get_cc_config_params(outgoing);
+	if (!cc_params) {
+		return;
+	}
+	if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) {
 		/* This sort of CCBS only works if using generic CC. For native, we would end up sending
 		 * a CC request for a non-existent call. The far end will reject this every time
 		 */
@@ -3423,16 +3428,19 @@
 	}
 
 	ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
-	cc_build_payload(outgoing, ast_channel_get_cc_config_params(outgoing), device_name,
-			dialstring, AST_CC_CCBS, &payload);
+	if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
+		dialstring, AST_CC_CCBS, &payload)) {
+		/* Something screwed up, we can't make a frame with this */
+		return;
+	}
 	ast_handle_cc_control_frame(incoming, outgoing, &payload);
 }
 
 void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
-		const char * const interface_name, const char * const dialable_name)
+	const char *monitor_type, const char * const device_name, const char * const dialable_name)
 {
 	struct ast_control_cc_payload payload;
-	if (cc_build_payload(inbound, cc_params, interface_name, dialable_name, AST_CC_CCBS, &payload)) {
+	if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialable_name, AST_CC_CCBS, &payload)) {
 		/* Something screwed up. Don't try to handle this payload */
 		return;
 	}




More information about the asterisk-commits mailing list