Fun times with Asterisk dialplan logic

  • Here is the kind of advanced stuff I play with in FreePBX.

    exten => s,1,NoOp()
    ; Skip if this is an emergency call
    exten => s,n,GotoIf($["${EMERGENCYROUTE}"=="YES"]?emergencyrouteused)
    ; Check if the call has already been validated to go out, and skip the rest of the processing
    exten => s,n,GotoIf($["${OUTBOUND_ROUTE_NAME}"=="Call_Validated_to_go_Out"]?skipvalidation)
    ; Depending on the outbound route send the call to be validated
    ; NANPA style number dialed with a code
    exten => s,n,GotoIf($["${OUTBOUND_ROUTE_NAME}"=="NANPA_Dialed_with_Code"]?validatenanpa,s,1)
    ;More logic coming. For now, dump channel and terminate call.
    exten => s,n,DumpChan
    exten => s,n,Hangup()
    ; The call was an emegerncy dial, do no processing, but note the log.
    exten => s,n(emergencyrouteused),NoOp()
    exten => s,n,Log(NOTICE, 911 was dialed by extension ${FROMEXTEN})
    ; The call was validated, nothing else to do.
    exten => s,n(skipvalidation),NoOp()
    exten => s,1,NoOp()
    ; NANPA format means digit zero is 7 or 8 and digit one is a 1 
    ; digits two through ten should be a 10 digit number
    ; the last five digits are the AUTCODE
    exten => s,n,Set(USERDIALED=${OUTNUM:2:10})
    exten => s,n,Set(AUTCODE=${OUTNUM:-5})
    ; Go check for a valid code
    exten => s,n,Set(RETURNTOCONTEXT=validatenanpa)
    exten => s,n,GoTo(checkvalidautcode,s,1)
    ; Return location if AUTCODE is valid
    exten => s,n(autcodevalid),NoOp()
    ; Check if the AUTCODE has a CID associated with it. 
    ; If there is no CID jump to autcidno, otherwise autcidyes
    exten => s,n,GotoIf($["${AUTCODECIDNUM}" == ""]?autcidno:autcidyes)
    exten => s,n,Hangup()
    exten => s,n(autcidyes),NoOp()
    exten => s,n,Log(NOTICE, The AUTCODE of ${AUTCODE} has an associated CID of ${AUTCODECIDNUM}. Forcing it to apply.
    exten => s,n(autcidno),NoOp()
    ; Go back to outbound route logic with the "secret" prefix of 8675309 (Jenny) that will match the pattern to get to an outboud trunk
    exten => s,n,Goto(outbound-allroutes,8675309${USERDIALED},1)
    exten => s,n,Hangup()
    ; This context checks that the AUTCODE value (last five digits) exists in the `autcodes` table
    ; See func_odbc.conf for the SQL statement.
    ; This context requires that the variable RETURNTOCONTEXT be set in by the context that calls it
    ; This context also requres that the calling context have a line labeled autcodevalid to return to
    exten => s,1,NoOp()
    ; Start a rety counter.
    exten => s,n,Set(RETRYCODE=0)
    ; If code is invalid, user is prompted to try again and the call is sent back to here
    exten => s,n(tryagain),NoOp()
    ; Check the database for the autcode. SQL query returns the `id` of the row if found
    ; if no rows are returned jump to badaut, if something is returned jump to goodaut
    exten => s,n,GotoIf($[${ODBCROWS} = 0]?badaut,1:goodaut,1)
    exten => s,n,Hangup()
    exten => badaut,1,NoOp()
    exten => badaut,n(notfound),Log(NOTICE, The AUTCODE of ${AUTCODE} was not found, user needs to try again)
    ; Increment the fail counter
    exten => badaut,n,Set(RETRYCODE=$[${RETRYCODE} + 1])
    ; If the user has failed 3 times (or more somehow) jump to toomanytries
    exten => badaut,n,GotoIf($[${RETRYCODE} >= 3]?toomanytries,1)
    ; Tell them the code was bad and to try again
    exten => badaut,n,Playback(you-entered)
    exten => badaut,n,Playback(access-code)
    exten => badaut,n,SayDigits(${AUTCODE})
    exten => badaut,n,Playback(vm-pls-try-again)
    exten => badaut,n,Set(TIMEOUT(response)=10)
    exten => badaut,n,Read(AUTCODE,access-code,5,,2,5)
    ; If the entered code was 5 digits jump back up to try again, otherwise jump up to not found
    exten => badaut,n,GotoIf($[${LEN(${AUTCODE})}==5]?s,tryagain:notfound)
    exten => badaut,n,Hangup()
    exten => goodaut,1,NoOp()
    exten => goodaut,n,Log(NOTICE, The AUTCODE of ${AUTCODE} was found, let call proceed)
    ; The code was found, so go back to the context that we came from at the spot marked autcodevalid
    exten => goodaut,n,GoTo(${RETURNTOCONTEXT},s,autcodevalid)
    exten => goodaut,n,Hangup()
    exten => toomanytries,1,NoOp()
    exten => toomanytries,n,Log(NOTICE, The user failed to enter a valid AUTCODE too many times)
    ; The user the dialed the code wrong too many times, hangup the call
    exten => toomanytries,n,Playback(sorry)
    exten => toomanytries,n,Playback(goodbye)
    exten => toomanytries,n,Hangup()

  • I appreciate your liberal use of comments in your files even if it all means nothing to me 🙂
    Would you mind giving a quick overview on exactly what is happening here for those of us who haven't played with Asterisk's conf files?

  • Start with a normal outbound route named NANPA_Dialed_with_Code.
    Give it a dialpattern of [78]1NXXNXXXXXXXXXXX

    When a user dials 81800555121298765 it will match that pattern for this outbound route. The outbound route will send the call to a trunk.

    Prior to the call getting to the trunk, the the built in context named [macro-dialout-trunk-predial-hook] is executed.

    The first thing it does is check if the call was routed via a route marked emergency, if so, jump to that label.

    If not, it checks the name of the route used as shown. Since it matches one of the if logics, it jumps to the context validatenanpa at position s,1.

    This context pulls apart the number as noted in the comments and then attempts to validate the autcode (short for authorization code).

    If you cannot follow the logic from there, me explaining more wont really help..

  • @JaredBusch said in Fun times with Asterisk dialplan logic:


    Perfect, that was very helpful and makes it perfectly clear.

  • @manxam said in Fun times with Asterisk dialplan logic:

    @JaredBusch said in Fun times with Asterisk dialplan logic:


    Perfect, that was very helpful and makes it perfectly clear.

    This NANPA:

    Not this one, it is totally different: (Thank you Japan)

  • So I was at my computer and thought I would share a few screenshots.

    Here is the outbound route list.


    This is what the Dial Pattenr looks like for one of them.


    Both of those NANPA routes send to the Catch_All trunk.


    Trunks available


    This trunk would simply hangup the call if a call actually gets to it.


    But calls never get to that trunk as noted in the previous posts.

  • @JaredBusch : Funny that you posted that as I actually had to go LOOK UP NANPA when you had mentioned it above and, at first, wondered what it had to do with the Japanese dating scene.. 🙂