summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2011-04-26 22:18:41 +0000
committerRichard Mudgett <rmudgett@digium.com>2011-04-26 22:18:41 +0000
commit24b6939496125def6253dc723e890e116250e79e (patch)
tree9c7aed6c59c1184f23ca3d631a64aefef399e4d1 /main
parent47a6dacf290e0a18622ac63645106616283c3500 (diff)
Merged revisions 315645 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r315645 | rmudgett | 2011-04-26 17:14:31 -0500 (Tue, 26 Apr 2011) | 21 lines The 'e' special extension fails to trigger in at least two cases. The 'e' extension is a fall back for the 'i', 't', or 'T' extensions if any of them do not exist. Many of the places the 'e' extension was supposed to be invoked fail because the priority was set wrong. There were two places where the 'e' extension was not even checked for fall back. * Made invoke the 'e' extension similarly to the previous 'i', 't', or 'T' extension check and added the 'e' extension as a fall back to the two missing locations. * Prioritized and optimized some hangup tests associated with the 'e' extension. (closes issue #19136) Reported by: kshumard Tested by: rmudgett Review: https://reviewboard.asterisk.org/r/1196/ ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@315649 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/pbx.c133
1 files changed, 89 insertions, 44 deletions
diff --git a/main/pbx.c b/main/pbx.c
index 6b75c77e2..366139675 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -3233,7 +3233,18 @@ static struct ast_datastore_info exception_store_info = {
.destroy = exception_store_free,
};
-int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
+/*!
+ * \internal
+ * \brief Set the PBX to execute the exception extension.
+ *
+ * \param chan Channel to raise the exception on.
+ * \param reason Reason exception is raised.
+ * \param priority Dialplan priority to set.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int raise_exception(struct ast_channel *chan, const char *reason, int priority)
{
struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
struct pbx_exception *exception = NULL;
@@ -3255,10 +3266,16 @@ int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
ast_string_field_set(exception, context, chan->context);
ast_string_field_set(exception, exten, chan->exten);
exception->priority = chan->priority;
- set_ext_pri(chan, "e", 0);
+ set_ext_pri(chan, "e", priority);
return 0;
}
+int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
+{
+ /* Priority will become 1, next time through the AUTOLOOP */
+ return raise_exception(chan, reason, 0);
+}
+
static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
{
struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
@@ -4838,30 +4855,41 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
&found, 1))) {
- if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT)
- && ast_exists_extension(c, c->context, "T", 1,
- S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
- set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
- /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
- memset(&c->whentohangup, 0, sizeof(c->whentohangup));
- ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
- } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT)
- && ast_exists_extension(c, c->context, "e", 1,
- S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
- pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT");
- /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
- memset(&c->whentohangup, 0, sizeof(c->whentohangup));
- ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
- } else if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
+ if (!ast_check_hangup(c)) {
+ ++c->priority;
+ continue;
+ }
+
+ /* Check softhangup flags. */
+ if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
continue;
- } else if (ast_check_hangup(c)) {
- ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
- c->exten, c->priority);
+ }
+ if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
+ if (ast_exists_extension(c, c->context, "T", 1,
+ S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
+ set_ext_pri(c, "T", 1);
+ /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
+ memset(&c->whentohangup, 0, sizeof(c->whentohangup));
+ ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
+ continue;
+ } else if (ast_exists_extension(c, c->context, "e", 1,
+ S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
+ raise_exception(c, "ABSOLUTETIMEOUT", 1);
+ /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
+ memset(&c->whentohangup, 0, sizeof(c->whentohangup));
+ ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
+ continue;
+ }
+
+ /* Call timed out with no special extension to jump to. */
error = 1;
break;
}
- c->priority++;
+ ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
+ c->exten, c->priority);
+ error = 1;
+ break;
} /* end while - from here on we can use 'break' to go out */
if (found && res) {
/* Something bad happened, or a hangup has been requested. */
@@ -4895,7 +4923,7 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
error = 1;
} else {
- pbx_builtin_raise_exception(c, "ERROR");
+ raise_exception(c, "ERROR", 1);
continue;
}
}
@@ -4903,20 +4931,29 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
continue;
- } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT)
- && ast_exists_extension(c, c->context, "T", 1,
+ }
+ if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
+ if (ast_exists_extension(c, c->context, "T", 1,
S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
- set_ext_pri(c, "T", 1);
- /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
- memset(&c->whentohangup, 0, sizeof(c->whentohangup));
- ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
- continue;
- } else {
- if (c->cdr)
- ast_cdr_update(c);
- error = 1;
- break;
+ set_ext_pri(c, "T", 1);
+ /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
+ memset(&c->whentohangup, 0, sizeof(c->whentohangup));
+ ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
+ continue;
+ } else if (ast_exists_extension(c, c->context, "e", 1,
+ S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
+ raise_exception(c, "ABSOLUTETIMEOUT", 1);
+ /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
+ memset(&c->whentohangup, 0, sizeof(c->whentohangup));
+ ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
+ continue;
+ }
+ /* Call timed out with no special extension to jump to. */
}
+ if (c->cdr)
+ ast_cdr_update(c);
+ error = 1;
+ break;
}
}
if (error)
@@ -4942,7 +4979,7 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
set_ext_pri(c, "i", 1);
} else if (ast_exists_extension(c, c->context, "e", 1,
S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
- pbx_builtin_raise_exception(c, "INVALID");
+ raise_exception(c, "INVALID", 1);
} else {
ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
c->name, c->exten, c->context);
@@ -4992,9 +5029,11 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
set_ext_pri(c, "i", 1);
} else if (ast_exists_extension(c, c->context, "e", 1,
S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
- pbx_builtin_raise_exception(c, "INVALID");
+ raise_exception(c, "INVALID", 1);
} else {
- ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
+ ast_log(LOG_WARNING,
+ "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
+ dst_exten, c->context);
found = 1; /* XXX disable message */
break;
}
@@ -5006,9 +5045,11 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
set_ext_pri(c, "t", 1);
} else if (ast_exists_extension(c, c->context, "e", 1,
S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
- pbx_builtin_raise_exception(c, "RESPONSETIMEOUT");
+ raise_exception(c, "RESPONSETIMEOUT", 1);
} else {
- ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
+ ast_log(LOG_WARNING,
+ "Timeout, but no rule 't' or 'e' in context '%s'\n",
+ c->context);
found = 1; /* XXX disable message */
break;
}
@@ -9405,18 +9446,22 @@ static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
res = ast_waitfordigit(chan, ms);
if (!res) {
- if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1,
+ if (ast_check_hangup(chan)) {
+ /* Call is hungup for some reason. */
+ res = -1;
+ } else if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1,
S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
ast_verb(3, "Timeout on %s, continuing...\n", chan->name);
- } else if (chan->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
- ast_verb(3, "Call timeout on %s, checking for 'T'\n", chan->name);
- res = -1;
} else if (ast_exists_extension(chan, chan->context, "t", 1,
S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
ast_verb(3, "Timeout on %s, going to 't'\n", chan->name);
set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
+ } else if (ast_exists_extension(chan, chan->context, "e", 1,
+ S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
+ raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */
} else {
- ast_log(LOG_WARNING, "Timeout but no rule 't' in context '%s'\n", chan->context);
+ ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n",
+ chan->context);
res = -1;
}
}