From d7da31797996c13b030debcc6d3dd8879743e93d Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Mon, 22 Nov 2004 22:11:10 +0000 Subject: [PATCH] Add improved macro functionality (bug #2905) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4317 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_dial.c | 61 +++++++++++++++-- include/asterisk/pbx.h | 4 +- pbx.c | 146 +++++++++++++++++++++++++---------------- 3 files changed, 149 insertions(+), 62 deletions(-) diff --git a/apps/app_dial.c b/apps/app_dial.c index 176fec5405..564ff86821 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -68,7 +68,13 @@ static char *descrip = " that are assigned to you.\n" " 'r' -- indicate ringing to the calling party, pass no audio until answered.\n" " 'm' -- provide hold music to the calling party until answered.\n" -" 'M(x) -- Executes the macro (x) upon connect of the call\n" +" 'M(x[^arg]) -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n" +" Also, the macro can set the MACRO_RESULT variable to do the following:\n" +" -- ABORT - Hangup both legs of the call.\n" +" -- CONGESTION - Behave as if line congestion was encountered.\n" +" -- BUSY - Behave as if a busy signal was encountered. (n+101)\n" +" -- CONTINUE - Hangup the called party and continue on in the dialplan.\n" +" -- GOTO:^^ - Transfer the call.\n" " 'h' -- allow callee to hang up by hitting *.\n" " 'H' -- allow caller to hang up by hitting *.\n" " 'C' -- reset call detail record for this call.\n" @@ -484,7 +490,7 @@ static int dial_exec(struct ast_channel *chan, void *data) char *sdtmfptr; char sdtmfdata[256] = ""; char *stack,*var; - char *mac = NULL, macroname[256] = ""; + char *mac = NULL, *macroname = NULL; char status[256]=""; char toast[80]; int play_to_caller=0,play_to_callee=0; @@ -492,9 +498,10 @@ static int dial_exec(struct ast_channel *chan, void *data) char *varname; int vartype; char *outbound_group = NULL; - + char *macro_result = NULL, *macro_transfer_dest = NULL; int digit = 0; time_t start_time, answer_time, end_time; + struct ast_app *app = NULL; if (!data) { ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n"); @@ -661,7 +668,7 @@ static int dial_exec(struct ast_channel *chan, void *data) /* Get the macroname from the dial option string */ if ((mac = strstr(transfer, "M("))) { hasmacro = 1; - strncpy(macroname, mac + 2, sizeof(macroname) - 1); + macroname = ast_strdupa(mac + 2); while (*mac && (*mac != ')')) *(mac++) = 'X'; if (*mac) @@ -1001,8 +1008,6 @@ static int dial_exec(struct ast_channel *chan, void *data) res = 0; if (hasmacro && macroname) { - void *app = NULL; - res = ast_autoservice_start(chan); if (res) { ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); @@ -1012,6 +1017,9 @@ static int dial_exec(struct ast_channel *chan, void *data) app = pbx_findapp("Macro"); if (app && !res) { + for(res=0;respriority + 101)) { + go_on = 1; + } + res = -1; + } + else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) { + strncpy(status, macro_result, sizeof(status) - 1); + go_on = 1; + res = -1; + } + else if (!strcasecmp(macro_result, "CONTINUE")) { + /* hangup peer and keep chan alive assuming the macro has changed + the context / exten / priority or perhaps + the next priority in the current exten is desired. + */ + go_on = 1; + res = -1; + } else if (!strcasecmp(macro_result, "ABORT")) { + /* Hangup both ends unless the caller has the g flag */ + res = -1; + } else if(!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) { + res = -1; + /* perform a transfer to a new extension */ + if(strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/ + /* no brainer mode... substitute ^ with | and feed it to builtin goto */ + for(res=0;rescontext, (exten && strcasecmp(exten, "BYEXTENSION")) ? exten : chan->exten, - pri, chan->cid.cid_num)) < 1) { - ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); - return -1; - } else - mode = 0; - } - /* At this point we have a priority and maybe an extension and a context */ - if (mode) - chan->priority += mode * ipri - 1; - else - chan->priority = ipri - 1; - if (exten && strcasecmp(exten, "BYEXTENSION")) - strncpy(chan->exten, exten, sizeof(chan->exten)-1); - if (context) - strncpy(chan->context, context, sizeof(chan->context)-1); - if (option_verbose > 2) + int res; + res = ast_parseable_goto(chan, (const char *) data); + if (!res && (option_verbose > 2)) ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1); - ast_cdr_update(chan); - return 0; + return res; } + int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t size) { struct ast_var_t *variables; @@ -5469,3 +5419,89 @@ int ast_context_verify_includes(struct ast_context *con) return res; } + +int ast_goto_if_exists(struct ast_channel *chan, char* context, char *exten, int priority) +{ + if(chan) { + if(ast_exists_extension(chan, + context ? context : chan->context, + exten ? exten : chan->exten, + priority ? priority : chan->priority, + chan->cid.cid_num)) { + return ast_async_goto(chan, + context ? context : chan->context, + exten ? exten : chan->exten, + priority ? priority : chan->priority); + } else + return -3; + } + + return -2; +} + +int ast_parseable_goto(struct ast_channel *chan, const char *goto_string) +{ + char *s; + char *exten, *pri, *context; + char *stringp=NULL; + int ipri; + int mode = 0; + + if (!goto_string || ast_strlen_zero(goto_string)) { + ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); + return -1; + } + s = ast_strdupa(goto_string); + stringp=s; + context = strsep(&stringp, "|"); + exten = strsep(&stringp, "|"); + if (!exten) { + /* Only a priority in this one */ + pri = context; + exten = NULL; + context = NULL; + } else { + pri = strsep(&stringp, "|"); + if (!pri) { + /* Only an extension and priority in this one */ + pri = exten; + exten = context; + context = NULL; + } + } + if (*pri == '+') { + mode = 1; + pri++; + } else if (*pri == '-') { + mode = -1; + pri++; + } + if (sscanf(pri, "%i", &ipri) != 1) { + if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, (exten && strcasecmp(exten, "BYEXTENSION")) ? exten : chan->exten, + pri, chan->cid.cid_num)) < 1) { + ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); + return -1; + } else + mode = 0; + } + /* At this point we have a priority and maybe an extension and a context */ + + if (exten && !strcasecmp(exten, "BYEXTENSION")) + exten = NULL; + + if (mode) + ipri = chan->priority + (ipri * mode); + + /* This channel is currently in the PBX */ + if (context && !ast_strlen_zero(context)) + strncpy(chan->context, context, sizeof(chan->context) - 1); + if (exten && !ast_strlen_zero(exten)) + strncpy(chan->exten, exten, sizeof(chan->context) - 1); + chan->priority = ipri - 1; + + ast_cdr_update(chan); + return 0; + +} + +