mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-13 16:21:01 +00:00
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 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@114773 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1619,6 +1619,13 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
|||||||
} else { /* Nobody answered, next please? */
|
} else { /* Nobody answered, next please? */
|
||||||
res = 0;
|
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 */
|
/* almost done, although the 'else' block is 400 lines */
|
||||||
} else {
|
} else {
|
||||||
const char *number;
|
const char *number;
|
||||||
@@ -1958,7 +1965,7 @@ out:
|
|||||||
senddialendevent(chan, pa.status);
|
senddialendevent(chan, pa.status);
|
||||||
ast_debug(1, "Exiting with DIALSTATUS=%s.\n", 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)
|
if (calldurationlimit)
|
||||||
chan->whentohangup = 0;
|
chan->whentohangup = 0;
|
||||||
res = 0;
|
res = 0;
|
||||||
@@ -2059,9 +2066,9 @@ static int retrydial_exec(struct ast_channel *chan, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res < 0)
|
if (res < 0 || res == AST_PBX_INCOMPLETE) {
|
||||||
break;
|
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)) {
|
if (onedigit_goto(chan, context, (char) res, 1)) {
|
||||||
res = 0;
|
res = 0;
|
||||||
break;
|
break;
|
||||||
|
@@ -42,6 +42,7 @@ extern "C" {
|
|||||||
#define AST_PBX_ERROR 1 /*!< Jump to the 'e' exten */
|
#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_KEEPALIVE 10 /*!< Destroy the thread, but don't hang up the channel */
|
||||||
#define AST_PBX_NO_HANGUP_PEER 11
|
#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 */
|
#define PRIORITY_HINT -1 /*!< Special Priority for a hint */
|
||||||
|
66
main/pbx.c
66
main/pbx.c
@@ -302,6 +302,7 @@ static int pbx_builtin_hangup(struct ast_channel *, void *);
|
|||||||
static int pbx_builtin_background(struct ast_channel *, void *);
|
static int pbx_builtin_background(struct ast_channel *, void *);
|
||||||
static int pbx_builtin_wait(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_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_keepalive(struct ast_channel *, void *);
|
||||||
static int pbx_builtin_resetcdr(struct ast_channel *, void *);
|
static int pbx_builtin_resetcdr(struct ast_channel *, void *);
|
||||||
static int pbx_builtin_setamaflags(struct ast_channel *, void *);
|
static int pbx_builtin_setamaflags(struct ast_channel *, void *);
|
||||||
@@ -579,6 +580,23 @@ static struct pbx_builtin {
|
|||||||
"value.\n"
|
"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,
|
{ "NoOp", pbx_builtin_noop,
|
||||||
"Do Nothing (No Operation)",
|
"Do Nothing (No Operation)",
|
||||||
" NoOp(): This application does nothing. However, it is useful for debugging\n"
|
" NoOp(): This application does nothing. However, it is useful for debugging\n"
|
||||||
@@ -696,12 +714,6 @@ static struct pbx_builtin {
|
|||||||
"See Also: Playback(application), Background(application).\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"
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ast_context *contexts;
|
static struct ast_context *contexts;
|
||||||
@@ -3582,6 +3594,8 @@ static int __ast_pbx_run(struct ast_channel *c)
|
|||||||
char dst_exten[256]; /* buffer to accumulate digits */
|
char dst_exten[256]; /* buffer to accumulate digits */
|
||||||
int pos = 0; /* XXX should check bounds */
|
int pos = 0; /* XXX should check bounds */
|
||||||
int digit = 0;
|
int digit = 0;
|
||||||
|
int invalid = 0;
|
||||||
|
int timeout = 0;
|
||||||
|
|
||||||
/* loop on priorities in this context/exten */
|
/* 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))) {
|
while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
|
||||||
@@ -3617,6 +3631,18 @@ static int __ast_pbx_run(struct ast_channel *c)
|
|||||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
|
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);
|
ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||||
error = 1;
|
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 {
|
} else {
|
||||||
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
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);
|
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 @@ static int __ast_pbx_run(struct ast_channel *c)
|
|||||||
* hangup. We have options, here. We can either catch the failure
|
* hangup. We have options, here. We can either catch the failure
|
||||||
* and continue, or we can drop out entirely. */
|
* 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
|
/*!\note
|
||||||
* If there is no match at priority 1, it is not a valid extension anymore.
|
* 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
|
* Try to continue at "i" (for invalid) or "e" (for exception) or exit if
|
||||||
@@ -3701,11 +3727,13 @@ static int __ast_pbx_run(struct ast_channel *c)
|
|||||||
|
|
||||||
if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
|
if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
|
||||||
break;
|
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);
|
set_ext_pri(c, dst_exten, 1);
|
||||||
else {
|
else {
|
||||||
/* No such extension */
|
/* No such extension */
|
||||||
if (!ast_strlen_zero(dst_exten)) {
|
if (!timeout && !ast_strlen_zero(dst_exten)) {
|
||||||
/* An invalid extension */
|
/* An invalid extension */
|
||||||
if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
|
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);
|
ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
|
||||||
@@ -7365,6 +7393,26 @@ static int pbx_builtin_keepalive(struct ast_channel *chan, void *data)
|
|||||||
return AST_PBX_KEEPALIVE;
|
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_OPTIONS(resetcdr_opts, {
|
||||||
AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
|
AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
|
||||||
AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
|
AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
|
||||||
|
Reference in New Issue
Block a user