[asterisk-commits] tilghman: trunk r114773 - in /trunk: apps/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 28 11:37:46 CDT 2008


Author: tilghman
Date: Mon Apr 28 11:37:45 2008
New Revision: 114773

URL: http://svn.digium.com/view/asterisk?view=rev&rev=114773
Log:
Add incomplete matching to PBX code and app_dial
(closes issue #12351)
 Reported by: Corydon76
 Patches: 
       20080402__pbx_incomplete__3.diff.txt uploaded by Corydon76 (license 14)
       pbx_incomplete_with_timeout.diff uploaded by fabled (license 448)
 Tested by: Corydon76, fabled

Modified:
    trunk/apps/app_dial.c
    trunk/include/asterisk/pbx.h
    trunk/main/pbx.c

Modified: trunk/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_dial.c?view=diff&rev=114773&r1=114772&r2=114773
==============================================================================
--- trunk/apps/app_dial.c (original)
+++ trunk/apps/app_dial.c Mon Apr 28 11:37:45 2008
@@ -1619,6 +1619,13 @@
 		} else { /* Nobody answered, next please? */
 			res = 0;
 		}
+
+		/* SIP, in particular, sends back this error code to indicate an
+		 * overlap dialled number needs more digits. */
+		if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) {
+			res = AST_PBX_INCOMPLETE;
+		}
+
 		/* almost done, although the 'else' block is 400 lines */
 	} else {
 		const char *number;
@@ -1958,7 +1965,7 @@
 	senddialendevent(chan, pa.status);
 	ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
 
-	if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_KEEPALIVE)) {
+	if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_KEEPALIVE) && (res != AST_PBX_INCOMPLETE)) {
 		if (calldurationlimit)
 			chan->whentohangup = 0;
 		res = 0;
@@ -2059,9 +2066,9 @@
 			}
 		}
 
-		if (res < 0)
+		if (res < 0 || res == AST_PBX_INCOMPLETE) {
 			break;
-		else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
+		} else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
 			if (onedigit_goto(chan, context, (char) res, 1)) {
 				res = 0;
 				break;

Modified: trunk/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/pbx.h?view=diff&rev=114773&r1=114772&r2=114773
==============================================================================
--- trunk/include/asterisk/pbx.h (original)
+++ trunk/include/asterisk/pbx.h Mon Apr 28 11:37:45 2008
@@ -42,6 +42,7 @@
 #define AST_PBX_ERROR	        1	/*!< Jump to the 'e' exten */
 #define AST_PBX_KEEPALIVE	10	/*!< Destroy the thread, but don't hang up the channel */
 #define AST_PBX_NO_HANGUP_PEER	11
+#define AST_PBX_INCOMPLETE	12	/*!< Return to PBX matching, allowing more digits for the extension */
 /*! } */
 
 #define PRIORITY_HINT	-1	/*!< Special Priority for a hint */

Modified: trunk/main/pbx.c
URL: http://svn.digium.com/view/asterisk/trunk/main/pbx.c?view=diff&rev=114773&r1=114772&r2=114773
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Mon Apr 28 11:37:45 2008
@@ -302,6 +302,7 @@
 static int pbx_builtin_background(struct ast_channel *, void *);
 static int pbx_builtin_wait(struct ast_channel *, void *);
 static int pbx_builtin_waitexten(struct ast_channel *, void *);
+static int pbx_builtin_incomplete(struct ast_channel *, void *);
 static int pbx_builtin_keepalive(struct ast_channel *, void *);
 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
@@ -579,6 +580,23 @@
 	"value.\n"
 	},
 
+	{ "Incomplete", pbx_builtin_incomplete,
+	"returns AST_PBX_INCOMPLETE value",
+	"  Incomplete([n]): Signals the PBX routines that the previous matched extension\n"
+	"is incomplete and that further input should be allowed before matching can\n"
+	"be considered to be complete.  Can be used within a pattern match when\n"
+	"certain criteria warrants a longer match.\n"
+	"  If the 'n' option is specified, then Incomplete will not attempt to answer\n"
+	"the channel first.  Note that most channel types need to be in Answer state\n"
+	"in order to receive DTMF.\n"
+	},
+
+	{ "KeepAlive", pbx_builtin_keepalive,
+	"returns AST_PBX_KEEPALIVE value",
+	"  KeepAlive(): This application is chiefly meant for internal use with Gosubs.\n"
+	"Please do not run it alone from the dialplan!\n"
+	},
+
 	{ "NoOp", pbx_builtin_noop,
 	"Do Nothing (No Operation)",
 	"  NoOp(): This application does nothing. However, it is useful for debugging\n"
@@ -694,12 +712,6 @@
 	"    m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
 	"               Optionally, specify the class for music on hold within parenthesis.\n"
 	"See Also: Playback(application), Background(application).\n"
-	},
-
-	{ "KeepAlive", pbx_builtin_keepalive,
-	"returns AST_PBX_KEEPALIVE value",
-	"  KeepAlive(): This application is chiefly meant for internal use with Gosubs.\n"
-	"Please do not run it alone from the dialplan!\n"
 	},
 
 };
@@ -3582,6 +3594,8 @@
 		char dst_exten[256];	/* buffer to accumulate digits */
 		int pos = 0;		/* XXX should check bounds */
 		int digit = 0;
+		int invalid = 0;
+		int timeout = 0;
 
 		/* loop on priorities in this context/exten */
 		while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
@@ -3617,6 +3631,18 @@
 				ast_debug(1, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
 				ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
 				error = 1;
+			} else if (res == AST_PBX_INCOMPLETE) {
+				ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
+				ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
+
+				/* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
+				if (!ast_matchmore_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
+					invalid = 1;
+				} else {
+					ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
+					digit = 1;
+					pos = strlen(dst_exten);
+				}
 			} else {
 				ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
 				ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
@@ -3657,7 +3683,7 @@
 		 * hangup.  We have options, here.  We can either catch the failure
 		 * and continue, or we can drop out entirely. */
 
-		if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
+		if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
 			/*!\note
 			 * If there is no match at priority 1, it is not a valid extension anymore.
 			 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
@@ -3701,11 +3727,13 @@
 
 			if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
 				break;
-			if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
+			if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
+				timeout = 1;
+			if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
 				set_ext_pri(c, dst_exten, 1);
 			else {
 				/* No such extension */
-				if (!ast_strlen_zero(dst_exten)) {
+				if (!timeout && !ast_strlen_zero(dst_exten)) {
 					/* An invalid extension */
 					if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
 						ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
@@ -7365,6 +7393,26 @@
 	return AST_PBX_KEEPALIVE;
 }
 
+static int pbx_builtin_incomplete(struct ast_channel *chan, void *data)
+{
+	char *options = data;
+	int answer = 1;
+
+	/* Some channels can receive DTMF in unanswered state; some cannot */
+	if (!ast_strlen_zero(options) && strchr(options, 'n')) {
+		answer = 0;
+	}
+
+	/* If the channel is hungup, stop waiting */
+	if (ast_check_hangup(chan)) {
+		return -1;
+	} else if (chan->_state != AST_STATE_UP && answer) {
+		__ast_answer(chan, 0);
+	}
+
+	return AST_PBX_INCOMPLETE;
+}
+
 AST_APP_OPTIONS(resetcdr_opts, {
 	AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
 	AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),




More information about the asterisk-commits mailing list