Add autofallthrough mode
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4020 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
0b59f08c8d
commit
5c9fef377d
|
@ -21,6 +21,16 @@ static=yes
|
|||
; CLI command 'save dialplan' too
|
||||
;
|
||||
writeprotect=no
|
||||
;
|
||||
; If autofallthrough is set, then if an extension runs out of
|
||||
; things to do, it will terminate the call with BUSY, CONGESTION
|
||||
; or HANGUP depending on Asterisk's best guess (strongly recommended).
|
||||
;
|
||||
; If autofallthrough is not set, then if an extension runs out of
|
||||
; things to do, asterisk will wait for a new extension to be dialed
|
||||
; (this is the original behavior of Asterisk 1.0 and earlier).
|
||||
;
|
||||
autofallthrough=yes
|
||||
|
||||
; You can include other config files, use the #include command (without the ';')
|
||||
; Note that this is different from the "include" command that includes contexts within
|
||||
|
@ -121,34 +131,27 @@ exten => _91700XXXXXXX,1,Dial(IAX2/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel)
|
|||
; International long distance through trunk
|
||||
;
|
||||
exten => _9011.,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _9011.,n,Congestion
|
||||
|
||||
[trunkld]
|
||||
;
|
||||
; Long distance context accessed through trunk
|
||||
;
|
||||
exten => _91NXXNXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _91NXXNXXXXXX,n,Congestion
|
||||
|
||||
[trunklocal]
|
||||
;
|
||||
; Local seven-digit dialing accessed through trunk interface
|
||||
;
|
||||
exten => _9NXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _9NXXXXXX,n,Congestion
|
||||
|
||||
[trunktollfree]
|
||||
;
|
||||
; Long distance context accessed through trunk interface
|
||||
;
|
||||
exten => _91800NXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _91800NXXXXXX,n,Congestion
|
||||
exten => _91888NXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _91888NXXXXXX,n,Congestion
|
||||
exten => _91877NXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _91877NXXXXXX,n,Congestion
|
||||
exten => _91866NXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||
exten => _91866NXXXXXX,n,Congestion
|
||||
|
||||
[international]
|
||||
;
|
||||
|
@ -214,6 +217,7 @@ exten => s,n,DigitTimeout,5 ; Set Digit Timeout to 5 seconds
|
|||
exten => s,n,ResponseTimeout,10 ; Set Response Timeout to 10 seconds
|
||||
exten => s,n(restart),BackGround(demo-congrats) ; Play a congratulatory message
|
||||
exten => s,n(instruct),BackGround(demo-instruct) ; Play some instructions
|
||||
exten => s,n,WaitExten ; Wait for an extension to be dialed.
|
||||
|
||||
exten => 2,1,BackGround(demo-moreinfo) ; Give some more information.
|
||||
exten => 2,n,Goto(s,instruct)
|
||||
|
@ -281,6 +285,7 @@ exten => 8500,n,Goto(s,6)
|
|||
;
|
||||
;exten => s,1,Answer
|
||||
;exten => s,n,Background(thanks) ; "Thanks for calling press 1 for sales, 2 for support, ..."
|
||||
;exten => s,n,WaitExten
|
||||
;exten => 1,1,Goto(submenu,s,1)
|
||||
;exten => 2,1,Hangup
|
||||
;include => default
|
||||
|
@ -289,6 +294,7 @@ exten => 8500,n,Goto(s,6)
|
|||
;exten => s,1,Ringing ; Make them comfortable with 2 seconds of ringback
|
||||
;exten => s,n,Wait,2
|
||||
;exten => s,n,Background(submenuopts) ; "Thanks for calling the sales department. Press 1 for steve, 2 for..."
|
||||
;exten => s,n,WaitExten
|
||||
;exten => 1,1,Goto(default,steve,1)
|
||||
;exten => 2,1,Goto(default,mark,2)
|
||||
|
||||
|
|
|
@ -550,6 +550,11 @@ extern void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp
|
|||
|
||||
int ast_extension_patmatch(const char *pattern, const char *data);
|
||||
|
||||
/* Set "autofallthrough" flag, if newval is <0, does not acutally set. If
|
||||
set to 1, sets to auto fall through. If newval set to 0, sets to no auto
|
||||
fall through (reads extension instead). Returns previous value. */
|
||||
extern int pbx_set_autofallthrough(int newval);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
159
pbx.c
159
pbx.c
|
@ -177,6 +177,8 @@ char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name);
|
|||
|
||||
static struct varshead globals;
|
||||
|
||||
static int autofallthrough = 0;
|
||||
|
||||
static struct pbx_builtin {
|
||||
char name[AST_MAX_APP];
|
||||
int (*execute)(struct ast_channel *chan, void *data);
|
||||
|
@ -408,9 +410,10 @@ static struct pbx_builtin {
|
|||
|
||||
{ "WaitExten", pbx_builtin_waitexten,
|
||||
"Waits for some time",
|
||||
" Wait(seconds): Waits for the user to enter a new extension for the \n"
|
||||
" Wait([seconds]): Waits for the user to enter a new extension for the \n"
|
||||
"specified number of seconds, then returns 0. Seconds can be passed with\n"
|
||||
"fractions of a second. (eg: 1.5 = 1.5 seconds)\n"
|
||||
"fractions of a seconds (eg: 1.5 = 1.5 seconds) or if unspecified the\n"
|
||||
"default extension timeout will be used.\n"
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -1927,63 +1930,82 @@ int ast_pbx_run(struct ast_channel *c)
|
|||
c->_softhangup = 0;
|
||||
} else {
|
||||
/* Done, wait for an extension */
|
||||
waittime = 0;
|
||||
if (digit)
|
||||
waittime = c->pbx->dtimeout;
|
||||
else
|
||||
else if (!autofallthrough)
|
||||
waittime = c->pbx->rtimeout;
|
||||
while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
|
||||
/* As long as we're willing to wait, and as long as it's not defined,
|
||||
keep reading digits until we can't possibly get a right answer anymore. */
|
||||
digit = ast_waitfordigit(c, waittime * 1000);
|
||||
if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
|
||||
c->_softhangup = 0;
|
||||
if (waittime) {
|
||||
while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
|
||||
/* As long as we're willing to wait, and as long as it's not defined,
|
||||
keep reading digits until we can't possibly get a right answer anymore. */
|
||||
digit = ast_waitfordigit(c, waittime * 1000);
|
||||
if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
|
||||
c->_softhangup = 0;
|
||||
} else {
|
||||
if (!digit)
|
||||
/* No entry */
|
||||
break;
|
||||
if (digit < 0)
|
||||
/* Error, maybe a hangup */
|
||||
goto out;
|
||||
exten[pos++] = digit;
|
||||
waittime = c->pbx->dtimeout;
|
||||
}
|
||||
}
|
||||
if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
|
||||
/* Prepare the next cycle */
|
||||
strncpy(c->exten, exten, sizeof(c->exten)-1);
|
||||
c->priority = 1;
|
||||
} else {
|
||||
if (!digit)
|
||||
/* No entry */
|
||||
break;
|
||||
if (digit < 0)
|
||||
/* Error, maybe a hangup */
|
||||
goto out;
|
||||
exten[pos++] = digit;
|
||||
waittime = c->pbx->dtimeout;
|
||||
/* No such extension */
|
||||
if (!ast_strlen_zero(exten)) {
|
||||
/* An invalid extension */
|
||||
if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
|
||||
pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
|
||||
strncpy(c->exten, "i", sizeof(c->exten)-1);
|
||||
c->priority = 1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* A simple timeout */
|
||||
if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
|
||||
strncpy(c->exten, "t", sizeof(c->exten)-1);
|
||||
c->priority = 1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c->cdr) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
|
||||
ast_cdr_update(c);
|
||||
}
|
||||
} else {
|
||||
if (option_verbose > 0) {
|
||||
char *status;
|
||||
status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
|
||||
if (!status)
|
||||
status = "UNKNOWN";
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
|
||||
if (!strcasecmp(status, "CONGESTION"))
|
||||
res = pbx_builtin_congestion(c, "10");
|
||||
else if (!strcasecmp(status, "CHANUNAVAIL"))
|
||||
res = pbx_builtin_congestion(c, "10");
|
||||
else if (!strcasecmp(status, "BUSY"))
|
||||
res = pbx_builtin_busy(c, "10");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
|
||||
/* Prepare the next cycle */
|
||||
strncpy(c->exten, exten, sizeof(c->exten)-1);
|
||||
c->priority = 1;
|
||||
} else {
|
||||
/* No such extension */
|
||||
if (!ast_strlen_zero(exten)) {
|
||||
/* An invalid extension */
|
||||
if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
|
||||
pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
|
||||
strncpy(c->exten, "i", sizeof(c->exten)-1);
|
||||
c->priority = 1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* A simple timeout */
|
||||
if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
|
||||
strncpy(c->exten, "t", sizeof(c->exten)-1);
|
||||
c->priority = 1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c->cdr) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
|
||||
ast_cdr_update(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstpass)
|
||||
|
@ -2045,6 +2067,15 @@ int ast_pbx_start(struct ast_channel *c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pbx_set_autofallthrough(int newval)
|
||||
{
|
||||
int oldval;
|
||||
oldval = autofallthrough;
|
||||
if (oldval != newval)
|
||||
autofallthrough = newval;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function locks contexts list by &conlist, search for the right context
|
||||
* structure, leave context list locked and call ast_context_remove_include2
|
||||
|
@ -4717,13 +4748,27 @@ static int pbx_builtin_wait(struct ast_channel *chan, void *data)
|
|||
static int pbx_builtin_waitexten(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int ms;
|
||||
|
||||
int res;
|
||||
/* Wait for "n" seconds */
|
||||
if (data && atof((char *)data)) {
|
||||
if (data && atof((char *)data))
|
||||
ms = atof((char *)data) * 1000;
|
||||
return ast_waitfordigit(chan, ms);
|
||||
else if (chan->pbx)
|
||||
ms = chan->pbx->rtimeout * 1000;
|
||||
else
|
||||
ms = 10000;
|
||||
res = ast_waitfordigit(chan, ms);
|
||||
if (!res) {
|
||||
if (ast_exists_extension(chan, chan->context, "t", 1, chan->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Timeout on %s\n", chan->name);
|
||||
strncpy(chan->exten, "t", sizeof(chan->exten));
|
||||
chan->priority = 0;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Timeout but no rule 't' in context '%s'\n", chan->context);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int pbx_builtin_background(struct ast_channel *chan, void *data)
|
||||
|
|
|
@ -42,6 +42,7 @@ static char *registrar = "pbx_config";
|
|||
|
||||
static int static_config = 0;
|
||||
static int write_protect_config = 1;
|
||||
static int autofallthrough_config = 0;
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
|
||||
|
||||
|
@ -1629,6 +1630,10 @@ static int pbx_load_module(void)
|
|||
"static"));
|
||||
write_protect_config = ast_true(ast_variable_retrieve(cfg, "general",
|
||||
"writeprotect"));
|
||||
|
||||
autofallthrough_config = ast_true(ast_variable_retrieve(cfg, "general",
|
||||
"autofallthrough"));
|
||||
|
||||
v = ast_variable_browse(cfg, "globals");
|
||||
while(v) {
|
||||
memset(realvalue, 0, sizeof(realvalue));
|
||||
|
@ -1774,6 +1779,8 @@ static int pbx_load_module(void)
|
|||
for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
|
||||
ast_context_verify_includes(con);
|
||||
|
||||
pbx_set_autofallthrough(autofallthrough_config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue