[asterisk-commits] rmudgett: branch rmudgett/dahdi_ccss r242087 - /team/rmudgett/dahdi_ccss/chan...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jan 21 16:11:38 CST 2010


Author: rmudgett
Date: Thu Jan 21 16:11:34 2010
New Revision: 242087

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=242087
Log:
Add ability to do the actual CC recall by chan_dahdi.

*  Added i<span> to the DAHDI dialstring to restrict channel selection to
the specified ISDN span.  The CC_INTERFACES channel variable will contain
a modified dialstring for the ISDN CC recall with the ISDN channel
restriction parameter inserted.
*  Fixed the DAHDI c/r/d dialing options broken earlier in the CCSS
branch.

Modified:
    team/rmudgett/dahdi_ccss/channels/chan_dahdi.c
    team/rmudgett/dahdi_ccss/channels/sig_pri.c
    team/rmudgett/dahdi_ccss/channels/sig_pri.h

Modified: team/rmudgett/dahdi_ccss/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/dahdi_ccss/channels/chan_dahdi.c?view=diff&rev=242087&r1=242086&r2=242087
==============================================================================
--- team/rmudgett/dahdi_ccss/channels/chan_dahdi.c (original)
+++ team/rmudgett/dahdi_ccss/channels/chan_dahdi.c Thu Jan 21 16:11:34 2010
@@ -2806,6 +2806,65 @@
 	ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
 }
 
+/*!
+ * \internal
+ * \brief Make a dialstring for native ISDN CC to recall properly.
+ * \since 1.8
+ *
+ * \param priv Channel private control structure.
+ * \param buf Where to put the modified dialstring.
+ * \param buf_size Size of modified dialstring buffer.
+ *
+ * \details
+ * original dialstring:
+ * DAHDI/[i<span>-]<channel#>[c|r<cadance#>|d][/extension[/options]]
+ * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
+ *
+ * The modified dialstring will have prefixed the channel-group section
+ * with the ISDN channel restriction.
+ *
+ * buf:
+ * DAHDI/i<span>-<channel#>[c|r<cadance#>|d][/extension[/options]]
+ * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
+ *
+ * The routine will check to see if the ISDN channel restriction is already
+ * in the original dialstring.
+ *
+ * \return Nothing
+ */
+static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
+{
+	char *dial;
+	struct dahdi_pvt *pvt;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(tech);	/* channel technology token */
+		AST_APP_ARG(group);	/* channel/group token */
+		//AST_APP_ARG(ext);	/* extension token */
+		//AST_APP_ARG(opts);	/* options token */
+		//AST_APP_ARG(other);	/* Any remining unused arguments */
+	);
+
+	pvt = priv;
+	dial = ast_strdupa(pvt->dialstring);
+	AST_NONSTANDARD_APP_ARGS(args, dial, '/');
+	if (!args.tech) {
+		ast_copy_string(buf, pvt->dialstring, buf_size);
+		return;
+	}
+	if (!args.group) {
+		/* Append the ISDN span channel restriction to the dialstring. */
+		snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
+		return;
+	}
+	if (args.group[0] == 'i') {
+		/* The ISDN span channel restriction is already in the dialstring. */
+		ast_copy_string(buf, pvt->dialstring, buf_size);
+		return;
+	}
+	/* Insert the ISDN span channel restriction into the dialstring. */
+	snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
+}
+
 static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri);
 
 static struct sig_pri_callback dahdi_pri_callbacks =
@@ -2825,6 +2884,7 @@
 	.set_rdnis = my_pri_set_rdnis,
 	.new_nobch_intf = dahdi_new_pri_nobch_channel,
 	.get_orig_dialstring = my_get_orig_dialstring,
+	.make_cc_dialstring = my_pri_make_cc_dialstring,
 };
 #endif	/* defined(HAVE_PRI) */
 
@@ -11948,9 +12008,17 @@
 	return tmp;
 }
 
-static int is_group_or_channel_match(struct dahdi_pvt *p, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
-{
-	/* First, check group matching */
+static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
+{
+#if defined(HAVE_PRI)
+	if (0 < span) {
+		/* The channel must be on the specified PRI span. */
+		if (!p->pri || p->pri->span != span) {
+			return 0;
+		}
+	}
+#endif	/* defined(HAVE_PRI) */
+	/* check group matching */
 	if (groupmatch) {
 		if ((p->group & groupmatch) != groupmatch)
 			/* Doesn't match the specified group, try the next one */
@@ -12168,13 +12236,29 @@
 	return p;
 }
 
-static struct dahdi_pvt *determine_starting_point(char *data, ast_group_t *groupmatch, int *channelmatch, int *backwards, int *roundrobin, int *rr_starting_point)
+struct dahdi_starting_point {
+	/*! Group matching mask.  Zero if not specified. */
+	ast_group_t groupmatch;
+	/*! DAHDI channel to match with.  -1 if not specified. */
+	int channelmatch;
+	/*! Round robin saved search location index. (Valid if roundrobin TRUE) */
+	int rr_starting_point;
+	/*! ISDN span where channels can be picked (Zero if not specified) */
+	int span;
+	/*! Analog channel distinctive ring cadance index. */
+	int cadance;
+	/*! Dialing option. c/r/d if present and valid. */
+	char opt;
+	/*! TRUE if to search the channel list backwards. */
+	char backwards;
+	/*! TRUE if search is done with round robin sequence. */
+	char roundrobin;
+};
+static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
 {
 	char *dest;
 	char *s;
-	char opt = 0;
 	int x;
-	int y = 0;
 	int res = 0;
 	struct dahdi_pvt *p;
 	AST_DECLARE_APP_ARGS(args,
@@ -12187,8 +12271,11 @@
 	/*
 	 * data is ---v
 	 * Dial(DAHDI/pseudo[/extension[/options]])
-	 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
-	 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
+	 * Dial(DAHDI/[i<span>-]<channel#>[c|r<cadance#>|d][/extension[/options]])
+	 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
+	 *
+	 * i - ISDN span channel restriction.
+	 *     Used by CC to ensure that the CC recall goes out the same span.
 	 *
 	 * g - channel group allocation search forward
 	 * G - channel group allocation search backward
@@ -12201,7 +12288,7 @@
 	 */
 
 	if (data) {
-		dest = ast_strdupa((char *)data);
+		dest = ast_strdupa(data);
 	} else {
 		ast_log(LOG_WARNING, "Channel requested with no data\n");
 		return NULL;
@@ -12212,24 +12299,47 @@
 		return NULL;
 	}
 
+	/* Initialize the output parameters */
+	memset(param, 0, sizeof(*param));
+	param->channelmatch = -1;
+
+	if (args.group[0] == 'i') {
+		/* Extract the ISDN span channel restriction specifier. */
+		res = sscanf(args.group + 1, "%30d", &x);
+		if (res < 1) {
+			ast_log(LOG_WARNING, "Unable to determine ISDN span %s\n", data);
+			return NULL;
+		}
+		param->span = x;
+
+		/* Remove the ISDN span channel restriction specifier. */
+		s = strchr(args.group, '-');
+		if (!s) {
+			ast_log(LOG_WARNING, "Bad format for ISDN span %s\n", data);
+			return NULL;
+		}
+		args.group = s + 1;
+		res = 0;
+	}
 	if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
 		/* Retrieve the group number */
 		s = args.group + 1;
-		if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
-			ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
+		res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
+		if (res < 1) {
+			ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
 			return NULL;
 		}
-		*groupmatch = ((ast_group_t) 1 << x);
+		param->groupmatch = ((ast_group_t) 1 << x);
 
 		if (toupper(args.group[0]) == 'G') {
 			if (args.group[0] == 'G') {
-				*backwards = 1;
+				param->backwards = 1;
 				p = ifend;
 			} else
 				p = iflist;
 		} else {
 			if (args.group[0] == 'R') {
-				*backwards = 1;
+				param->backwards = 1;
 				p = round_robin[x]?round_robin[x]->prev:ifend;
 				if (!p)
 					p = ifend;
@@ -12238,59 +12348,57 @@
 				if (!p)
 					p = iflist;
 			}
-			*roundrobin = 1;
+			param->roundrobin = 1;
+			param->rr_starting_point = x;
 		}
 	} else {
 		s = args.group;
 		if (!strcasecmp(s, "pseudo")) {
 			/* Special case for pseudo */
 			x = CHAN_PSEUDO;
-			*channelmatch = x;
-		} else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
-			ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
-			return NULL;
+			param->channelmatch = x;
 		} else {
-			*channelmatch = x;
+			res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
+			if (res < 1) {
+				ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
+				return NULL;
+			} else {
+				param->channelmatch = x;
+			}
 		}
 
 		p = iflist;
 	}
-	if (*roundrobin) {
-		*rr_starting_point = x;
-	}
+
+	if (param->opt == 'r' && res < 3) {
+		ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
+		param->opt = '\0';
+	}
+
 	return p;
 }
 
 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
 {
-	ast_group_t groupmatch = 0;
-	int channelmatch = -1;
-	int roundrobin = 0;
 	int callwait = 0;
 	int unavailreason = 0;
 	struct dahdi_pvt *p;
 	struct ast_channel *tmp = NULL;
-	char opt=0;
-	int res=0, y=0;
-	int backwards = 0;
 	struct dahdi_pvt *exitpvt;
 	int channelmatched = 0;
 	int groupmatched = 0;
 	int transcapdigital = 0;
-	int rr_starting_point;
-
-/* BUGBUG need to figure out how to do a CC recall call. */
-	p = determine_starting_point(data, &groupmatch, &channelmatch, &backwards, &roundrobin, &rr_starting_point);
+	struct dahdi_starting_point start;
+
+	p = determine_starting_point(data, &start);
 	/* Search for an unowned channel */
 	exitpvt = p;
 	ast_mutex_lock(&iflock);
 	while (p && !tmp) {
-		if (roundrobin)
-			round_robin[rr_starting_point] = p;
-#if 0
-		ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
-#endif
-		if (is_group_or_channel_match(p, groupmatch, &groupmatched, channelmatch, &channelmatched)
+		if (start.roundrobin)
+			round_robin[start.rr_starting_point] = p;
+
+		if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
 			&& available(p, &unavailreason)) {
 			ast_debug(1, "Using channel %d\n", p->channel);
 
@@ -12315,22 +12423,25 @@
 			}
 
 			/* Make special notes */
-			if (res > 1) {
-				if (opt == 'c') {
-					/* Confirm answer */
-					p->confirmanswer = 1;
-				} else if (opt == 'r') {
-					/* Distinctive ring */
-					if (res < 3)
-						ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
-					else
-						p->distinctivering = y;
-				} else if (opt == 'd') {
-					/* If this is an ISDN call, make it digital */
-					transcapdigital = AST_TRANS_CAP_DIGITAL;
-				} else {
-					ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
-				}
+			switch (start.opt) {
+			case '\0':
+				/* No option present. */
+				break;
+			case 'c':
+				/* Confirm answer */
+				p->confirmanswer = 1;
+				break;
+			case 'r':
+				/* Distinctive ring */
+				p->distinctivering = start.cadance;
+				break;
+			case 'd':
+				/* If this is an ISDN call, make it digital */
+				transcapdigital = AST_TRANS_CAP_DIGITAL;
+				break;
+			default:
+				ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
+				break;
 			}
 
 			p->outgoing = 1;
@@ -12358,7 +12469,7 @@
 #ifdef HAVE_OPENR2
 next:
 #endif
-		if (backwards) {
+		if (start.backwards) {
 			p = p->prev;
 			if (!p)
 				p = ifend;
@@ -12404,19 +12515,17 @@
  */
 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
 {
-	struct dahdi_pvt *p, *exitpvt;
-	ast_group_t groupmatch = 0;
+	struct dahdi_pvt *p;
+	struct dahdi_pvt *exitpvt;
+	struct dahdi_starting_point start;
 	int groupmatched = 0;
-	int channelmatch = -1;
 	int channelmatched = 0;
-	int backwards = 0;
-	int roundrobin = 0;
-	int rr_starting_point = 0;
-
-	p = determine_starting_point((char *)dest, &groupmatch, &channelmatch, &backwards, &roundrobin, &rr_starting_point);
+
+	p = determine_starting_point(dest, &start);
+	ast_mutex_lock(&iflock);
 	exitpvt = p;
 	for (;;) {
-		if (is_group_or_channel_match(p, groupmatch, &groupmatched, channelmatch, &channelmatched)) {
+		if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
 			/* We found a potential match. call the callback */
 			struct ast_str *device_name;
 			char *dash;
@@ -12472,14 +12581,15 @@
 				break;
 			}
 		}
-		p = backwards ? p->prev : p->next;
+		p = start.backwards ? p->prev : p->next;
 		if (!p) {
-			p = backwards ? ifend : iflist;
+			p = start.backwards ? ifend : iflist;
 		}
 		if (p == exitpvt) {
 			break;
 		}
 	}
+	ast_mutex_unlock(&iflock);
 	return 0;
 }
 

Modified: team/rmudgett/dahdi_ccss/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/dahdi_ccss/channels/sig_pri.c?view=diff&rev=242087&r1=242086&r2=242087
==============================================================================
--- team/rmudgett/dahdi_ccss/channels/sig_pri.c (original)
+++ team/rmudgett/dahdi_ccss/channels/sig_pri.c Thu Jan 21 16:11:34 2010
@@ -159,7 +159,20 @@
 	if (p->calls->get_orig_dialstring) {
 		return p->calls->get_orig_dialstring(p->chan_pvt);
 	}
+	ast_log(LOG_ERROR, "get_orig_dialstring callback not defined\n");
 	return "";
+}
+#endif	/* defined(HAVE_PRI_CCSS) */
+
+#if defined(HAVE_PRI_CCSS)
+static void sig_pri_make_cc_dialstring(struct sig_pri_chan *p, char *buf, size_t buf_size)
+{
+	if (p->calls->make_cc_dialstring) {
+		p->calls->make_cc_dialstring(p->chan_pvt, buf, buf_size);
+	} else {
+		ast_log(LOG_ERROR, "make_cc_dialstring callback not defined\n");
+		buf[0] = '\0';
+	}
 }
 #endif	/* defined(HAVE_PRI_CCSS) */
 
@@ -1732,22 +1745,23 @@
  */
 static int sig_pri_cc_available(struct sig_pri_pri *pri, int chanpos, long cc_id, enum ast_cc_service_type service)
 {
-	struct ast_channel *owner;
+	struct sig_pri_chan *pvt;
 	struct ast_cc_config_params *cc_params;
 	struct sig_pri_cc_monitor_instance *monitor;
 	enum ast_cc_monitor_policies monitor_policy;
 	int core_id;
 	int res;
 	char device_name[AST_CHANNEL_NAME];
-
-	owner = pri->pvts[chanpos]->owner;
-
-	core_id = ast_cc_get_current_core_id(owner);
+	char dialstring[AST_CHANNEL_NAME];
+
+	pvt = pri->pvts[chanpos];
+
+	core_id = ast_cc_get_current_core_id(pvt->owner);
 	if (core_id == -1) {
 		return -1;
 	}
 
-	cc_params = ast_channel_get_cc_config_params(owner);
+	cc_params = ast_channel_get_cc_config_params(pvt->owner);
 	if (!cc_params) {
 		return -1;
 	}
@@ -1764,10 +1778,10 @@
 		 * If it is AST_CC_MONITOR_ALWAYS and native fails we will attempt the fallback
 		 * later in the call to sig_pri_cc_generic_check().
 		 */
-		ast_channel_get_device_name(owner, device_name, sizeof(device_name));
+		ast_channel_get_device_name(pvt->owner, device_name, sizeof(device_name));
+		sig_pri_make_cc_dialstring(pvt, dialstring, sizeof(dialstring));
 		monitor = sig_pri_cc_monitor_instance_init(core_id, pri, cc_id, device_name);
-		res = ast_queue_cc_frame(owner, sig_pri_cc_type_name,
-			sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service);
+		res = ast_queue_cc_frame(pvt->owner, sig_pri_cc_type_name, dialstring, service);
 		if (res) {
 			ao2_unlink(sig_pri_cc_monitors, monitor);
 			monitor->cc_id = -1;
@@ -1775,8 +1789,8 @@
 		ao2_ref(monitor, -1);
 		break;
 	case AST_CC_MONITOR_GENERIC:
-		ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
-			sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service);
+		ast_queue_cc_frame(pvt->owner, AST_CC_GENERIC_MONITOR_TYPE,
+			sig_pri_get_orig_dialstring(pvt), service);
 		/* Say it failed to force caller to cancel native CC. */
 		break;
 	}
@@ -4180,6 +4194,7 @@
 #ifdef SUPPORT_USERUSER
 	const char *useruser;
 #endif
+	int core_id;
 	int pridialplan;
 	int dp_strip;
 	int prilocaldialplan;
@@ -4496,7 +4511,35 @@
 		pri_sr_set_useruser(sr, useruser);
 #endif
 
-	if (pri_setup(p->pri->pri, p->call, sr)) {
+#if defined(HAVE_PRI_CCSS)
+	if (ast_cc_is_recall(ast, &core_id)) {
+		struct sig_pri_cc_monitor_instance *monitor;
+
+		/* This is a CC recall call. */
+		monitor = sig_pri_find_cc_monitor_by_core_id(core_id);
+		if (monitor) {
+			/* If this fails then we have monitor instance ambiguity. */
+			ast_assert(p->pri == monitor->pri);
+
+			if (pri_cc_call(p->pri->pri, monitor->cc_id, p->call, sr)) {
+				/* The CC recall call failed for some reason. */
+				ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n",
+					monitor->name);
+				ao2_ref(monitor, -1);
+				pri_rel(p->pri);
+				pri_sr_free(sr);
+				return -1;
+			}
+			ao2_ref(monitor, -1);
+		} else {
+			core_id = -1;
+		}
+	} else
+#endif	/* defined(HAVE_PRI_CCSS) */
+	{
+		core_id = -1;
+	}
+	if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) {
 		ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
 			c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
 		pri_rel(p->pri);

Modified: team/rmudgett/dahdi_ccss/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/dahdi_ccss/channels/sig_pri.h?view=diff&rev=242087&r1=242086&r2=242087
==============================================================================
--- team/rmudgett/dahdi_ccss/channels/sig_pri.h (original)
+++ team/rmudgett/dahdi_ccss/channels/sig_pri.h Thu Jan 21 16:11:34 2010
@@ -81,8 +81,8 @@
 	void (* const set_rdnis)(void *pvt, const char *rdnis);
 	void (* const queue_control)(void *pvt, int subclass);
 	int (* const new_nobch_intf)(struct sig_pri_pri *pri);
-
 	const char *(* const get_orig_dialstring)(void *pvt);
+	void (* const make_cc_dialstring)(void *pvt, char *buf, size_t buf_size);
 };
 
 #define NUM_DCHANS		4	/*!< No more than 4 d-channels */




More information about the asterisk-commits mailing list