Skip to main content

Asterisk - Trunk Group Limits

I had a need to limit the number of calls sent out on a specific trunk, and wanted a generic way to do it.  I have been using this on Asterisk 1.6.1.x, but it may be supported on other versions.  At the core it uses GROUP and GROUP_COUNT functions.  Hopefully this will be of use to someone else.

; Trunk subroutine:
;  Arguments: Arg1 = Device to call (i.e. DAHDI/G4 or SIP/gateway)
;             Arg2 = Group name for call limiting (defaults to "trunk")
;             Arg3 = Max calls to this device (Default 10)
;  Note:  This does santize the extension to only be numeric (0-9)
;  Call:  Gosub(trunk-group,${EXTEN},1(<-- Args -->))
exten => _X.,1,Verbose(3,trunk-group: Start)
exten => _X.,n,Set(LOCAL(trunk)=${ARG1})                                        ; Device to call out on (Required)
exten => _X.,n,Set(LOCAL(grpname)=$["${ARG2}" ? ${ARG2} :: trunk])              ; Grouping name for call counts (default: trunk)
exten => _X.,n,Set(LOCAL(maxcalls)=$["${ARG3}" ? ${ARG3} :: 10])                ; Maximum calls in the counter (default: 10)
exten => _X.,n,Set(LOCAL(number)=${FILTER(0-9,${EXTEN})})                       ; Sanitize the called number (has to be numeric)
; Argument validation
exten => _X.,n,GotoIf($[${ISNULL(${trunk})}]?failure)                           ; You have to tell me what to call out on...
exten => _X.,n,Verbose(3,trunk-group: Group ${grpname}, Maxcalls ${maxcalls})
; Start processing the call
exten => _X.,n,Set(GROUP()=${grpname})                                          ; Invoke the counting
exten => _X.,n,Verbose(3,trunk-group: Group ${grpname}, Current Calls ${GROUP_COUNT(${grpname})})
exten => _X.,n,Gotoif($[ ${GROUP_COUNT(${grpname})} > ${maxcalls} ]?BUSY)      ; Give a busy indication if this call will exceed the limit
; Success
exten => _X.,n,Dial(${trunk}/${number})                                         ; Dial out the trunk, passing the extension
exten => _X.,n,Goto(${DIALSTATUS})                                              ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,CANCEL)
exten => _X.,n,Return()                                                         ; Shouldn't get here, but for good measure
; Failure / Busy
exten => _X.,n(failure),Verbose(1,trunk-group: An error occured, exiting)
exten => _X.,n(BUSY),Busy()
exten => _X.,n,Return()
exten => _X.,n(NOANSWER),Congestion()
exten => _X.,n,Return()
exten => _X.,n(CHANUNAVAIL),Congestion()
exten => _X.,n,Return()
exten => _X.,n(CONGESTION),Congestion()
exten => _X.,n,Return()
exten => _X.,n(CANCEL),Hangup()
exten => _X.,n,Return()