DISA, contexts, and timeouts

There seems to have been a change in FreePBX 2.5, which is a step backwards in usefulness, IMHO, related to DISA.

One thing I am very vigilant about with any phone system install, is the use of appropriate, non-ambiguous dial plans (for Asterisk, Zap channels, and SIP phones).

When someone dials a three-digit internal extension, I want their system to dial immediately, not waiting a few seconds until they finish dialing. Same with outgoing calls. I make sure there is no ambiguity in the dial plan, so they never need to wait for a timeout or press # after their dialing. Explaining to a customer that they have to wait for a timeout, or modify their dialing behaviour, isn’t acceptable, IMHO.

Customers (and myself) greatly appreciate a tight, unambiguous dialplan in daily usage. It makes a system feel more responsive and professional all around. I like to do a professional job for customers.

In FreePBX 2.4, the [disa] contexts all called the DISA() app with the from-internal context; from-internal has all of the non-ambiguous dial plan goodness, so when you dial in from outside, enter an extension or an outside number, things would dial immediately. Again, very responsive, no timeouts, no need for #.

In FreePBX 2.5, the [disa] contexts instead call DISA() with a new [disa-dial] context, which includes a horrible “_.” pattern in it; this 100% guarantees needing to wait for a digit timeout.

When I upgraded them to 2.5 my customers (and myself, at first!) though all the DISAs were broken, not realizing that if we waited for 10 seconds or pressed #, it would complete the call. ("_." are dial-plan sins in my book, although I do use something like them for international dialing, which can be so varied in length, it’s justified.)

I realize I can crank down the timeout, but I don’t see this as a solution; you still have to wait, and if you end up pausing to check/read the number you’re dialing, things time out. Things were done in the right manner in 2.4, and now they’re worse…

I tried adding a [dial-disa-custom] context that includes my from-internal context, but as long as that “_.” pattern is in [dial-disa], things still end up waiting for the digit tiemout, which is unacceptable…

Any other elegant suggestions for getting the old, immediately-dial-upon-dialplan-match behaviour back? I guess I’ll hack the FreePBX source for now, but I always prefer avoiding that where possible (so my patch doesn’t get clobbered on the next module update).

I realize the [disa-dial] adds utility, in going back to the dialtone after a failed DISA dial attempt; but it’s too great a cost, in ruining the immediacy of a good dial plan’s dialing…


Another thing broken in FreePBX’s 2.5 DISA: the optional “Caller ID” field seems to be ignored. It used to be possible to have a user dial in through a DISA, and appear to be a specific internal extension; this is quite useful, having the appearance of coming from that user’s extension (for purposes of callbacks, voicemail, etc.) This config field now seems to be ignored.

(Also, in 2.5, inboud CID-only routes seem to have broken; where an empty DID field used to be “s”, which worked, they are now replaced with “_.” [my nemesis, again!], which loses out to the catch-all inbound route. An easy fix for this is to put an “s” in the DID field for any CID-only route, to get the old, working behaviour back. This is with Asterisk 1.4.19.)

(I should add that I absolutely love FreePBX, and it makes working with Asterisk so incredibly convenient. I appreciate all the work that the team has done on the project. My comments are mainly intended to continue the incremental improvements with this awesome package!)


I don’t think the developers take as much notice of these messages as they do tickets filed in the bug reporting system. Especially in a case where a new version “breaks” previous behavior, I’d file one or more tickets at http://www.freepbx.org/trac/newticket - your issues will almost certainly get more consideration there than here.

Thanks, I’m new to the FreePBX community, thanks for the pointer, will file a report…

Concerning the DISA change, it really came down to a tradeoff between the points you make (which are valid) and the very painful issue of the call ending if you mis-dial (which DISA is known for), hit busy signals, need to dial multiple people, etc. In addition there were other problems with DISA, it was very flakey in several regards.

I believe the tradeoffs involved were well worth the added utility. It’s not to say there may not be ways to get the best of both worlds by other changes and we are always open to that. However, to go back to the implementation where you can only make a single call I believe strongly is going backwards.

As far as the CID issue, if that is broken, file a bug so someone can have a look. As far as the “_.” issue, that in itself is a bug and needs to be addressed as it breaks on some 1.2 systems. (But it will still be something like _[0-9*#))

As far as the DID issue, are you completely up-to-date? There was an issue with the ‘s’ being removed which did break some systems but has been addressed. It has been months since I looked at it and I don’t recall the details other than the implementation was a bit subtle.

If you are having an issue or believe there is something that is still broke with it, feel free to file a bug on that but please provide some very specific information and the scenario that is going on so that it is understood.

Concerning my original problem: I agree that the new features added (which broke the dialplan dialing) are useful.

I think it should be possible to achieve both ends, possibly by having disa going to the from-internal context (as before), and then having the from-internal context, after dialing, check for a DISA environment variable, and doing a Goto(${DISA}) (like the [disa-dial] context does now, but as part of the real from-internal context, preserving the dial plan behaviour).

I might play around with this, and if I come up with something workable, suggest a patch.

Regarding the CID failure, I’ll see if I can track down why/where that is getting lost (as compared to 2.4). It’s definitely different, in 2.4 I got the internal extension associated with the DISA showing up on caller-id, on 2.5 I get the external number. I’ll hunt it down a bit more, and post a specific bug report.

Regarding the CID-with-empty-DID, 2.5 is definitely putting a “_./callerid#” in the plan where it used to put “s/callerid#”, and Asterisk 1.4.19 is definitely favouring the “catchall” over it. A googling shows other people complaining about this same behaviour. (Possibly some versions of Asterisk don’t behave this way, which is why the devs haven’t seen it?)

[Update: I checed the CID failure on DISA, and now it seems to be working :S Weird, maybe I was mistaken when I was fighting with the CID-with-empty-DID problem. I did several tests just now, and the caller ID indeed seems to take on the disa’s extension. If this reoccurs, I’ll narrow it down and post a bug.]

P.S.: I am fully up to date on all modules in FreePBX 2.5, and as mentioned, am using Asterisk 1.4.19.

More thoughts: I think rather than having the disa’s go to subroutine-like context [disa-dial], they should more naturally go to [from-internal]; a DISA should behave like an internal call, so this makes sense. The extra wrapper of [disa-dial] seems to mess up things, mainly due to the _. pattern match.

Instead, we should go directly to [from-internal], but at the appropriate places for failed user calls, check for a variable indicating a pending DISA (DISA_CONTEXT, perhaps), and if so, branch to that context to try again; this is very similar to the IVR_CONTEXT variable, which causes failed calls to extensions to pop back to the IVR at [${DISA_CONTEXT},return,1].

It’s very much the same type of thing you want to achieve. The hook would have to be added at the very least for extensions and outbound routes (the things you typically use DISA for, and can mis-dial). It could be added to other apps as well (things in [from-internal-additional] are all candidates, but extensions and outbound routes are the obvious ones).

Even just doing it for outbound routes might be sufficient; these are he things most likely to be mis-dialed or busy (longer numbers).

running directly through from-internal would probably be problematic given the ‘infinite’ code paths a call could take with all internal dialplan. An alternative option would be to provide dialpatterns for the ‘disa-dial’ context (or for each disa and create a separate disa-dial for each instance). This would add complexity but at the same time add a level of control into which dialpatterns you allowed to be dialed. (you could restrict international, only allow international, only allow internal numbers, etc.)

as far as the ext-did discussion, we have the following code in extensions.conf:

include => from-pstn-custom                     ; create this context in extensions_custom.conf to include customizations
include => ext-did
include => ext-did-post-custom
include => from-did-direct    ; MODIFICATOIN (PL) for findmefollow if enabled, should be bofore ext-local
include => ext-did-catchall   ; THIS MUST COME AFTER ext-did

this means that if you have a match in ext-did it WILL take precedence over ext-did-catchall since the latter will never even be reviewed, it is the way asterisk works. So if you are not getting that call into that context, it means it is not matching. (You can remove the ext-did-catchall and should see the call completely fail). So the question is why is it not matching as I know I have tested CID only routes with no DID.

As far as other changes, you can see that the catchall route will take any remaining call and send it back into the ext-did context with s as the extension:

include => ext-did-catchall-custom
exten => _.,1,Noop(Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.)
exten => _.,n,Goto(ext-did,s,1)

I agree the many paths through from-internal is problematic; I do like the idea of multiple dial-disa sections. They'll be auto-generated, so it's not unweildy code-wise, and it's not the first case where many copies of chunks are made in the templates, one for each extension/trunk/route/etc.. And as you said, it adds a hook for greater flexibility per-disa.

Understood re: the catchall and precedence. Upon further investigation, here's what's happening:

*With* and "s" for the DID, and my cell phone's number as the CID, I get these chunks:

exten => s/19995551212,1,Set(__FROM_DID=${EXTEN})
exten => s/19995551212,n,Gosub(app-blacklist-check,s,1)
exten => s/19995551212,n,ExecIf($[ "${CALLERID(name)}" = "" ] ,Set,CALLERID(name)=${CALLERID(num)})
exten => s/19995551212,n,Set(__CALLINGPRES_SV=${CALLINGPRES_${CALLINGPRES}})
exten => s/19995551212,n,SetCallerPres(allowed_not_screened)
exten => s/19995551212,n,Set(__ALERT_INFO=n=Duck) 
exten => s/19995551212,n,Goto(disa,3,1)

Nothing in [ext-did-0002] of relevance.

Now, when I leave the DID field empty, and put my cell phone’s number in the CID, I get the following:

Nothing of relevance in [ext-did-0001].

exten => _./19995551212,1,Set(__FROM_DID=${EXTEN})
exten => _./19995551212,n,Goto(s,1)
exten => s/19995551212,1,ExecIf($["${FROM_DID}" = ""],Set,__FROM_DID=${EXTEN})
exten => s/19995551212,n,Gosub(app-blacklist-check,s,1)
exten => s/19995551212,n,ExecIf($[ "${CALLERID(name)}" = "" ] ,Set,CALLERID(name)=${CALLERID(num)})
exten => s/19995551212,n,Set(__CALLINGPRES_SV=${CALLINGPRES_${CALLINGPRES}})
exten => s/19995551212,n,SetCallerPres(allowed_not_screened)
exten => s/19995551212,n,Set(__ALERT_INFO=n=Duck)
exten => s/19995551212,n,Goto(disa,3,1)

Whoa, what’s with that first _.? (Oh, how I hate that pattern! :slight_smile:

If it weren’t there, things would probably be fine, the second chunk with the s/ is what we want. In the logs, I’m definitely seeing the “Goto(s,1)” being executed, thwarting the route…

Line 909 of admin/modules/core/functions.ini.php seems to be adding this.

It’s like leaving the DID field blank causes intentionally skipping the route if any non-blank DID is present (rather than matching everything). I guess one could use blank vs. “s” to distinguishing between “no DID is present” and “match any DID”, but I don’t think that’s terribly useful, and leaving the DID blank implies to me that it matches anything, not just lack of a DID…

So you’re correct, I’m not hitting the catchall, I’m hitting that _./# =>Goto(s,1) pattern that is included before the default s/# context (with the same end result).


here is a sneaky way to get rid of those two lines.

in extensions_custom.conf put the following three lines

exten => _./19995551212,1,Set(__FROM_DID=${EXTEN})
exten => _./19995551212,n,Goto(s,1)

Wow, you can do that? :stuck_out_tongue:

The context in a custom.conf is a great trick for tweaking things, thanks!

(I still think there’s a bug in the code that should be addressed, but that (-) thing is a great trick; probably not good to use in your normal coding, but for tweaking an auto-generated context, it’s handy.)

yes it works, and yes I probably should have said dirty rotten sneaky trick, but it works.

maybe I read too quickly, but I’m not getting where you are having an issue. Is it related to the second case being generated in ext-did-0002 instead of ext-did-0001? If that is the case, check the “CID Priority” box (or what ever it is called, I can’t recall). That will move it up.

Otherwise, either I read too quickly or I still don’t quite see what issue you are having.

I didn’t really notice the CID priority option; new in 2.5, I guess. That will probably do the trick.

Still, for a CID route with no DID specified (where there are no other matching DID routes) going to the default extension makes less sense to me, than actually using the route.

Basically, a CID route with no DID specified can never match anything (unless CID priority is checked), so it should at least generate an error, rather than expectation that it would match all DIDs with that CID.

(Also, the change in behaviour from 2.4 broke all my routes without notice. Not a biggie for me, more of a hassle for customers.)

The new structure, although more complex, solved some problems that previously existed on 2.4 such as the inability to have a CID only route which would take precedence of a call even if it came in on a DID that had it’s own route. There were a couple other issues as well though I don’t recall at the moment what they were.

As far as the catchall route coming first resulting in the behavior you are running into, vs. being placed in ext-did-0002, I am pretty sure it is structured that way for a good reason but it’s been a long day and right now I don’t recall the specifics of why, sorry.

Sorry for all the confusion… Sometimes it’s hard to trace the steps of which context is being followed, especially when the CID is playing a parts in asterisk’s choice of contexts.

The CID Priority thing did make my CID-only route work nicely, which is fine.

And yes, I do agree that having DID routes take priority, with an option for a CID-only route (that happens to match a did route) having a priority override is a good, additional bit of functionality.

The only confusion is the catch-all seems to take priority over the non-priority CID-only route. It could lead to confusion among newcomers, although this is probably minor, as the CID priority checkbox is right there, and a pretty obvious solution. (I was so used to the system, I never noticed that one new checkbox.)

The main issue, I think, is people who have CID-only routes, and upgrade to 2.5, will suddenly have those routes ineffective. The solution is easy, but it is still a break during an upgrade.

If you’ll bear with me, for my own enlightenment (so that I might help contribute more in the future :), I’m still a bit confused as to the flow. From my latest tests, I suspect the FreePBX-generated code is correct, but Asterisk is doing something unexpected:

Here’s my trace of things for a CID-only route, when no other DID matches:

  1. Set for CID priority:
    The _.####### pattern matches in [ext-did-0001], sets FROM_DID, and does a Goto(s,1)

This seems to go to [ext-did-0001],s/#######,1.

So s/#######,1 (my desired route’s execution) will be executed (and not the default s,1 context). The world is good.

That is, the current CID affects the branch, even in the case of Goto(s,1). Is this correct? (Sorry, I’m still learning some of these context subtleties.) This seems to be what happens.

  1. Not set for CID priority:

The _.####### pattern matches in [ext-did-0002], sets FROM_DID, and does a Goto(s,1).

However, instead of going to [ext-did-0002]'s s/#######,1 route handler, it goes to [ext-did-0001]'s s,1.

It would seem the intent was to go to [ext-did-0002]'s s/#######,1 route handler, parallel to case #1.

Further evidence that the intent wasn’t to go [ext-did-0001],s,1 is that the first thing s,1 Set(_FROM_DID=s), likely not what was intended, whereas the s/#######,1 version checks _FROM_DID before overwriting it with an ExecIf.

Both [ext-did-0001] and [ext-did-0002] are included (indirectly) from [from-pstn], so they should both be part of the [from-pstn] context, no? Why, then, in case #1 does the Goto(s,1) branch go to the s/#######,1 line, and in case #2 the branch goes to s,1 line? I’m not sure I see why there should be a difference in behaviour…? Both traces show a Goto(from-pstn,s,1) is being done, but in one case the s,1 exten is used, in another the s/####### exten is used. I’m confused.

I should add that I’m extremely impressed with how smoothly the FreePBX team handles upgrades overall. For most packages in this world, I would never upgrade a customer site without running another upgraded version in parallel first, verifying everything works, and then switching over. I’ve had such incredible luck with FreePBX module upgrades, that I have the confidence to upgrade things without worrying about everything breaking. It is done very well, better than most other packages out there. (Which is why this route thing not working, and the DISA dial delays being introduced, caught me off guard.) But for a major point release, those were fairly minor issues, and I have workarounds for both, now.

More testing… It does seem to be an inconsistency in Asterisk (1.4.19).

The current CALLERID(num) does seem to be honoured with Goto matching in Asterisk (the ext/CALLERID pattern has priority over one without).

In [ext-did-0002], the “_.#######,s” extension sets _FROM_DID and does a Goto(s,1):

exten => _./19995551212,1,Set(__FROM_DID=${EXTEN})
exten => _./19995551212,n,Goto(s,1)
exten => s/19995551212,1, … <= Where we should end up, but don’t

However, for some reason, this doesn’t jump to ext-did-0002,s/19025950424,1 but to ext-did-0001,s,1 instead. I’ve verified this carefully (Noop’s printing out their execution in ext-did-0001,s).

I added an explicit context to the Goto():

exten => _./19995551212,1,Set(__FROM_DID=${EXTEN})
exten => _./19995551212,n,Goto(ext-did-0002,s,1)
exten => s/19995551212,1, … <= Now we end up here!

This works. With this minor change (that should be redundant), even a non-priority CID-only route will be used if there are no otherwise matching DID’s.

Or am I missing something about the logic of included context?

In any case, I’m pretty sure branching to ext-did-0002,s,1 is the correct and originally intended thing to do, so expressing it more explicitly, and having it work, is probably a useful fix, no?

concerning your questions as to what is happening from an Asterisk perspective (why it is hitting one context over the other), I’m going to have to ask you to spend some time reading up on how Asterisk navigates the dialplan wrt to both contexts and additional CID info in the extensions.

As far as the intended behavior, as I had mentioned, I believe there was a reason why the ‘s’ paths were put in ext-did-0001 and when I can spend a few moments reviewing that code and the changes, we’ll determine if that was indeed the case or if change is warranted.

You need to keep in mind that this part of the code is going to behave differently trunks depending on how the calls are being delivered. The behavior has always varied slightly in the past and is one of the reasons that the changes were make, to have the option of giving more specific control to do all the alternatives an normalize the inconsistent behavior.

Hi everyone,

I read all the above comments and I would be grateful if someone would just tell me what do I need to change to make it when the last number is pressed the call is processed and there is no waiting or the need to press # to get it done.

I mean you we don’t need to press a # when using any standard phone why should this be any different for the freepbx.


I just revisited this issue the other day, and it still hasn’t been addressed. (I think the bug report I filed on it is marked to be addressed in a future version.)

I think it’s a fairly significant bug. If the dialplan otherwise can recognize with dialing is complete (which work on Zap lines, Iaxy’s, and others), then it should do the same with DISA. Requiring a # or waiting for a time out is not friendly to the users.

The extensions_custom override above is a nice dirty hack to achieve it.

My alternative is to hack the source. In /var/www/html/admin/modules/disa/functions.inc.php (line 108 for me), I changed:

$ext->add(‘disa’, $item[‘disa_id’], ‘’, new ext_disa(‘no-password,disa-dial’));


$ext->add(‘disa’, $item[‘disa_id’], ‘’, new ext_disa(‘no-password,from-internal’));

(And then made any GUI change that required a reload, to regenerate the conf files.)

Instead of going to the disa-dial context (which has that horrible ._ wildcard that blows the dialplan-end recognition), it simply goes to the dialing-as-an-internal-extension dialplan, which does the right/smart thing.

You lose the ability to redial on busy but that’s worse (IMHO) than that awful delay. The cumulative seconds/minutes spent waiting for that awkward delay (or requiring the user to press #) are far greater than the odd occasion when I get a busy number; and if the number’s busy [who doesn’t have voicemail these days???], then typically I don’t want to call someone else anyway…

Note, if you upgrade your DISA module, this hack will be overwritten, and you’ll have to reapply as appropriate…



That was fast response thank you. Ok so I modified the /var/www/html/admin/modules/disa/functions.inc.php

And then did the reload. However, I did not understand the point about: (And then made any GUI change that required a reload, to regenerate the conf files.)

Can you explain that?



The FreePBX GUI only updates all the .conf files when you make a change through the GUI. Manually hacking a source is not a change it would notice/consider.

Restarting/reloading asterisk is not enough, the config files won’t be updated.

So if you modify the source that creates the config files with this hack, the config files aren’t automatically regenerated.

You have to make some benign change (i.e. change the name of your disa, and change it back), so that FreePBX indicates “Apply Configuration Changes” in orange at the top; click on that, apply the changes, and it will create a new set of config files (extensions_additional.conf in particular) that will contain the updated disa/functions.inc.php changes…

If you look at your extensions_additional.conf and you see that in the [disa] section that the DISA(no-password,from-internal) lines are present, then your change worked.