From 20e56c9d36b76efb153ce2d694e09e16547f525e Mon Sep 17 00:00:00 2001
From: Richard Mudgett <rmudgett@digium.com>
Date: Fri, 6 Nov 2009 22:32:17 +0000
Subject: [PATCH] Created standard location to add options to chan_dahdi for
 ISDN dialing.

Dial(DAHDI/g1[/extension[/options]])
Current options:
K(<keypad_digits>)
R Reverse charging indication (Collect calls)

The earlier Dial(DAHDI/g1[/K<keypad_digits>][/extension] format was
variable and did not allow for the easy addition of more options.

The earlier 'C' prefix character for reverse charge indiation would
conflict with the a-d DTMF digits if ISDN uses them.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@228691 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 CHANGES               |  16 +++++-
 channels/chan_dahdi.c |  41 ++++++++------
 channels/sig_pri.c    | 127 +++++++++++++++++++-----------------------
 3 files changed, 92 insertions(+), 92 deletions(-)

diff --git a/CHANGES b/CHANGES
index f18e918d87..cba56f900e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -228,8 +228,6 @@ libpri channel driver (chan_dahdi) DAHDI changes
    dialing the redirected-to party.  You still have to set the
    REDIRECTING(to-xxx,i) and the REDIRECTING(from-xxx,i) values.  The call
    will update the redirecting-to presentation (COLR) when it becomes available.
- * Added Reverse Charging Indication receipt & transmission (requires latest
-   LibPRI).
  * Added the ability to ignore calls that are not in a Multiple Subscriber
    Number (MSN) list for PTMP CPE interfaces.
  * Added dynamic range compression support for dahdi channels.  It is
@@ -243,9 +241,21 @@ libpri channel driver (chan_dahdi) DAHDI changes
    Will reroute/deflect an outgoing call when receive the message.
    Can use the DAHDISendCallreroutingFacility to send the message for the
    supported switches.
+ * Added standard location to add options to chan_dahdi dialing:
+   Dial(DAHDI/g1[/extension[/options]])
+   Current options:
+   K(<keypad_digits>)
+   R Reverse charging indication
+ * Added Reverse Charging Indication (Collect calls) send/receive option.
+   Send reverse charging in SETUP message with the chan_dahdi R dialing option.
+   Dial(DAHDI/g1/extension/R)
+   Access received reverse charge in SETUP message by: ${CHANNEL(reversecharge)}
+   (requires latest LibPRI)
  * Added ability to send/receive keypad digits in the SETUP message.
-   Send keypad digits in SETUP message: Dial(DAHDI/g1[/K<keypad_digits>][/extension])
+   Send keypad digits in SETUP message with the chan_dahdi K(<keypad_digits>)
+   dialing option.  Dial(DAHDI/g1/[extension]/K(<keypad_digits>))
    Access any received keypad digits in SETUP message by: ${CHANNEL(keypad_digits)}
+   (requires latest LibPRI)
 
 Asterisk Manager Interface
 --------------------------
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 32344f77eb..e71f2ed914 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -12000,7 +12000,7 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
 	int unavailreason = 0;
 	struct dahdi_pvt *p;
 	struct ast_channel *tmp = NULL;
-	char *dest=NULL;
+	char *dest;
 	int x;
 	char *s;
 	char opt=0;
@@ -12009,12 +12009,18 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
 	struct dahdi_pvt *exitpvt;
 	int channelmatched = 0;
 	int groupmatched = 0;
+	AST_DECLARE_APP_ARGS(args,
+		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 */
+	);
 
 	/*
 	 * data is ---v
-	 * Dial(DAHDI/pseudo[/extension])
-	 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
-	 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
+	 * 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]])
 	 *
 	 * g - channel group allocation search forward
 	 * G - channel group allocation search backward
@@ -12032,12 +12038,15 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
 		ast_log(LOG_WARNING, "Channel requested with no data\n");
 		return NULL;
 	}
-	if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
-		/* Retrieve the group number */
-		char *stringp;
+	AST_NONSTANDARD_APP_ARGS(args, dest, '/');
+	if (!args.argc || ast_strlen_zero(args.group)) {
+		ast_log(LOG_WARNING, "No channel/group specified\n");
+		return NULL;
+	}
 
-		stringp = dest + 1;
-		s = strsep(&stringp, "/");
+	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);
 			return NULL;
@@ -12047,14 +12056,14 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
 		/* Lock the interface list */
 		ast_mutex_lock(&iflock);
 
-		if (toupper(dest[0]) == 'G') {
-			if (dest[0] == 'G') {
+		if (toupper(args.group[0]) == 'G') {
+			if (args.group[0] == 'G') {
 				backwards = 1;
 				p = ifend;
 			} else
 				p = iflist;
 		} else {
-			if (dest[0] == 'R') {
+			if (args.group[0] == 'R') {
 				backwards = 1;
 				p = round_robin[x]?round_robin[x]->prev:ifend;
 				if (!p)
@@ -12067,16 +12076,12 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
 			roundrobin = 1;
 		}
 	} else {
-		char *stringp;
-
-		stringp = dest;
-		s = strsep(&stringp, "/");
+		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) {
+		} 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;
 		} else {
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index ee4f9353d9..99be5a49bd 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -35,6 +35,7 @@
 #include "asterisk/utils.h"
 #include "asterisk/options.h"
 #include "asterisk/pbx.h"
+#include "asterisk/app.h"
 #include "asterisk/file.h"
 #include "asterisk/callerid.h"
 #include "asterisk/say.h"
@@ -3267,38 +3268,22 @@ void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdes
 	char *dial;
 	char *number;
 	char *subaddr;
-
-	/* Get private copy of dial string. */
+	AST_DECLARE_APP_ARGS(args,
+		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 */
+	);
+
+	/* Get private copy of dial string and break it up. */
 	dial = ast_strdupa(rdest);
+	AST_NONSTANDARD_APP_ARGS(args, dial, '/');
 
-	/* Skip channel selection section. */
-	number = strchr(dial, '/');
-	if (number) {
-		++number;
-	} else {
+	number = args.ext;
+	if (!number) {
 		number = "";
 	}
 
-#if defined(HAVE_PRI_SETUP_KEYPAD)
-	/*
-	 *  v--- number points here
-	 * /[K<keypad-digits>/]extension
-	 */
-	if (number[0] == 'K') {
-		/* Skip the keypad facility digits. */
-		number = strchr(number + 1, '/');
-		if (number) {
-			++number;
-		} else {
-			number = "";
-		}
-	}
-	/*
-	 *  v--- number points here
-	 * /extension
-	 */
-#endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
-
 	/* Find and extract dialed_subaddress */
 	subaddr = strchr(number, ':');
 	if (subaddr) {
@@ -3337,6 +3322,22 @@ void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdes
 	}
 }
 
+enum SIG_PRI_CALL_OPT_FLAGS {
+	OPT_KEYPAD =         (1 << 0),
+	OPT_REVERSE_CHARGE = (1 << 1),	/* Collect call */
+};
+enum SIG_PRI_CALL_OPT_ARGS {
+	OPT_ARG_KEYPAD = 0,
+
+	/* note: this entry _MUST_ be the last one in the enum */
+	OPT_ARG_ARRAY_SIZE,
+};
+
+AST_APP_OPTIONS(sig_pri_call_opts, BEGIN_OPTIONS
+	AST_APP_OPTION_ARG('K', OPT_KEYPAD, OPT_ARG_KEYPAD),
+	AST_APP_OPTION('R', OPT_REVERSE_CHARGE),
+END_OPTIONS);
+
 /*! \note Parsing must remain in sync with sig_pri_extract_called_num_subaddr(). */
 int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1)
 {
@@ -3355,6 +3356,14 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 #if defined(HAVE_PRI_SETUP_KEYPAD)
 	const char *keypad;
 #endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
+	AST_DECLARE_APP_ARGS(args,
+		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 */
+	);
+	struct ast_flags opts;
+	char *opt_args[OPT_ARG_ARRAY_SIZE];
 
 	ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n", ast->cid.cid_name, ast->cid.cid_num);
 
@@ -3368,45 +3377,20 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 		return -1;
 	}
 
-	ast_copy_string(dest, rdest, sizeof(dest));
-
 	p->dialdest[0] = '\0';
 	p->outgoing = 1;
 
-	c = strchr(dest, '/');
-	if (c) {
-		c++;
-	} else {
-		c = "";
+	ast_copy_string(dest, rdest, sizeof(dest));
+	AST_NONSTANDARD_APP_ARGS(args, dest, '/');
+	if (ast_app_parse_options(sig_pri_call_opts, &opts, opt_args, args.opts)) {
+		/* General invalid option syntax. */
+		return -1;
 	}
 
-#if defined(HAVE_PRI_SETUP_KEYPAD)
-	/*
-	 *  v--- c points here
-	 * /[K<keypad-digits>/]extension
-	 */
-	if (c[0] == 'K') {
-		/* Extract the keypad facility digits. */
-		keypad = c + 1;
-		c = strchr(keypad, '/');
-		if (c) {
-			/* Terminate the keypad facility digits. */
-			*c++ = '\0';
-		} else {
-			c = "";
-		}
-		if (ast_strlen_zero(keypad)) {
-			/* What no keypad digits? */
-			keypad = NULL;
-		}
-	} else {
-		keypad = NULL;
+	c = args.ext;
+	if (!c) {
+		c = "";
 	}
-	/*
-	 *  v--- c points here
-	 * /extension
-	 */
-#endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
 
 	/* setup dialed_subaddress if found */
 	ast_party_subaddress_init(&dialed_subaddress);
@@ -3545,16 +3529,6 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 		case 'r':
 			pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
 			break;
-#if defined(HAVE_PRI_REVERSE_CHARGE)
-		case 'C':
-			pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
-			break;
-#endif
-#if defined(HAVE_PRI_SETUP_KEYPAD)
-		case 'K':
-			/* Reserve this letter for keypad facility digits. */
-			break;
-#endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
 		default:
 			if (isalpha(c[p->stripmsd])) {
 				ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
@@ -3565,8 +3539,13 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 		c++;
 	}
 #if defined(HAVE_PRI_SETUP_KEYPAD)
-	if (keypad) {
+	if (ast_test_flag(&opts, OPT_KEYPAD)
+		&& !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
+		/* We have a keypad facility digits option with digits. */
+		keypad = opt_args[OPT_ARG_KEYPAD];
 		pri_sr_set_keypad_digits(sr, keypad);
+	} else {
+		keypad = NULL;
 	}
 	if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
 #endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
@@ -3584,6 +3563,12 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 	}
 #endif	/* defined(HAVE_PRI_SUBADDR) */
 
+#if defined(HAVE_PRI_REVERSE_CHARGE)
+	if (ast_test_flag(&opts, OPT_REVERSE_CHARGE)) {
+		pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
+	}
+#endif	/* defined(HAVE_PRI_REVERSE_CHARGE) */
+
 	ldp_strip = 0;
 	prilocaldialplan = p->pri->localdialplan - 1;
 	if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
-- 
GitLab