7

I'm having an intermittent issue where asterisk will play our greeting to the caller, and then drop the call instead of making our phones ring.

I'm unable to reproduce the problem with any phones I have here, and many callers get through just fine. Some callers though, run into the problem, and I can't find any pattern to it.

The bit of information I could find said it was caused by an error in evaluating a dialplan expression. I'm thinking it's this line:

exten => START,n,GotoIf($[${FORCE_CLOSED}=TRUE]?CLOSED,1)

But I'm not sure what's wrong with it.

I see the following error on the console:

[Apr  4 16:29:49] WARNING[27038]: ast_expr2.fl:459 ast_yyerror: ast_yyerror():  syntax error: syntax error, unexpected '=', expecting $end; Input:=TRUE^

Surrounding Console output:

-- Executing [START@AGInbound:1] Answer("IAX2/AtlantaTeliax-10086", "") in new stack
-- Executing [START@AGInbound:2] BackGround("IAX2/AtlantaTeliax-10086", 0000_AG_THANK_YOU_FOR_CALLING_AG") in new stack
--  Playing '0000_AG_THANK_YOU_FOR_CALLING_AG.slin' (language 'en')
[Apr  4 16:29:49] WARNING[27038]: ast_expr2.fl:459 ast_yyerror: ast_yyerror():  syntax error: syntax error, unexpected '=', expecting $end; Input:
=TRUE
^
[Apr  4 16:29:49] WARNING[27038]: ast_expr2.fl:463 ast_yyerror: If you have questions, please refer to doc/tex/channelvariables.tex in the asterisk source.
    -- Executing [START@AGInbound:3] GotoIf("IAX2/AtlantaTeliax-10086", "?CLOSED,1") in new stack
    -- Executing [START@AGInbound:4] GotoIfTime("IAX2/AtlantaTeliax-10086", "9:30-17:0|mon-fri|*|*?OPEN,1") in new stack
    -- Executing [START@AGInbound:5] GotoIfTime("IAX2/AtlantaTeliax-10086", "10:0-18:30|sat|*|*?OPEN,1") in new stack
    -- Executing [START@AGInbound:6] GotoIfTime("IAX2/AtlantaTeliax-10086", "12:0-17:0|sun|*|*?OPEN,1") in new stack

Relevant lines from the dial plan:

exten => START,1,Answer()
exten => START,n,Background(0000_AG_THANK_YOU_FOR_CALLING_AG)

; See if we're open
; Force Closed if no one's going to be answering
exten => START,n,GotoIf($[${FORCE_CLOSED}=TRUE]?CLOSED,1)

exten => START,n,GotoIfTime(${AG_WEEKDAY_OPEN_HOUR}:${AG_WEEKDAY_OPEN_MIN}-${AG$
exten => START,n,GotoIfTime(${AG_SATURDAY_OPEN_HOUR}:${AG_SATURDAY_OPEN_MIN}-${$
exten => START,n,GotoIfTime(${AG_SUNDAY_OPEN_HOUR}:${AG_SUNDAY_OPEN_MIN}-${AG_S$
; ...and we're not. But maybe the time of day has been overridden?
exten => START,n,GotoIf($[${OVERRIDE_TIME_OF_DAY}=TRUE]?OPEN,1)
; No override... We're definatly closed.
exten => START,n,Goto(CLOSED,1)

Any idea what's wrong with the expression? We recently upgraded from 1.4 to 1.6.

Nick
  • 4,433
  • 29
  • 67
  • 95

3 Answers3

2

In an Asterisk $[] expression, undefined variables do not return an implicit empty string or zero. They expand as "nothing" prior to evaluation of the expression, so after the variable is expanded (to nothing), it isn't visible to the expression parser. This causes the error already noted by Pablo Alsina:

GotoIf("IAX2/AtlantaTeliax-10086", "?CLOSED,1")

There are two ways to avoid this:

  1. Always give your variables reasonable defaults before you use them (as Pablo suggested).
  2. In any $[] expression, enclose your variables and literals with double-quotes. This will cause an undefined variable to be handled as an empty string, which can still be used for comparison purposes.

Personally, I try to do both. For example:

exten => START,n,Set(FORCE_CLOSED=FALSE)
exten => START,n,GotoIf($["${FORCE_CLOSED}"="TRUE"]?CLOSED,1)

Note the double-quotes around ${FORCE_CLOSED} and the comparison value. Even if the variable is undefined, the expression will have "" (an empty string) to compare against "TRUE".

Really, you can use any character you like, because it will just be tacked onto the variable expansion. It just gives you a literal value that is guaranteed to be there in case the variable is undefined. I like quotes because it makes the code resemble other programming languages. You could just as easily use something like $[x${FORCE_CLOSED}=xTRUE], which is commonly seen in Bourne shell scripting. The end result is the same.

James Sneeringer
  • 6,755
  • 23
  • 27
  • Is there way to define the variable only if it's undefined? Like if(!defined(FORCE_CLOSED) {FORCE_CLOSED=FALSE} ? – Nick Apr 15 '10 at 21:50
  • Not that I'm aware of, at least not with 1.4 (I haven't moved to 1.6 yet). The best I know of are the `EXISTS()` and `ISNULL()` functions. Both take "data" as their argument, not a variable name, so they aren't really testing the variable so much as what the variable expands to. They appear to be opposites of each other, with `EXISTS()` returning 1 if "data" is anything at all, and `ISNULL()` returning 1 if "data" is nothing. – James Sneeringer Apr 16 '10 at 15:49
0

Here's what I can tell you.

yyerror is an error from a parser generated by yacc.

The error complains of the =. So it seems that, on that line, the = is a construct that the grammar does not support.

Good luck on serverfault.com where this question is headed ...

bmargulies
  • 2,283
  • 3
  • 17
  • 20
  • That's what it seems like, but the problem is totally intermittent. For some calls, there's no error at all and it works just fine. If it were really a syntax error, wouldn't the problem occur for EVERY call that hit that line of the dial-plan, and not just some of them? – Nick Apr 04 '10 at 23:04
0

Who defines ${FORCE_CLOSED}?

From what I see, it seems that that variable sometimes does not get an initial value, and then the parser raises and error when you evaluate

GotoIf("IAX2/AtlantaTeliax-10086", "?CLOSED,1")

Check that the calls that raises an error have a reasonable value for FORCE_CLOSED

Pablo Alsina
  • 353
  • 2
  • 6
  • The variable is defined when a user dials a specific extension that sets it. For example, on Christmas eve, the employee would dial 221 before leaving, which sets the value to true. on the 26th, whoever returns to the office would then dial 220 to set it to "false" again. – Nick Apr 15 '10 at 21:49