The *MYSTERIOUS* extension 's'

Okay, so give an example of what you want it to do thereafter. The _X. matches all extensions that start with a numeric and you may continue to process within the test_ob context. Further, you could match (if you have devised your numbering plan in an intelligent way) as follows:

[code]context test_ob {
_1X. => {
NoOp(${CALLERID});
Macro(set-prs-cli|${CALLERIDNUM});
NoOp(${CALLID});
Dial(SIP/${EXTEN}@PSTNgw);
};

    _3000 => {
            VoiceMailMain();
    };

    _3XXX => {
            Dial(SIP/${EXTEN});
    };

    i => {
           Playback(invalid);
           Hangup();
    };

};[/code]

Where your numbering plan states that:

  • Everything starting with a 1 is external (of course for North American only, would need something different for international)
  • Voicemail may be reached at extension 3000
  • All internal extensions start with a 3 and are 4 digits long
  • If the users dials an invalid extension you play ‘invalid’ and disconnect

The only time you call the macro to set a specific CallerID is when you dial outside, otherwise for internal use it is the setting from sip.conf. Of course this is entirely programmable and may be whatever you want, but gives you an idea.

What do I want to do after the _X matches? Go back and start processing again and look for something else that matches.

Unfortunately the dial plan will not be that simple. Our users are going to be porting real PSTN numbers over, and there will be no rhym or reason to the numbers/extensions they use. We can’t map a _XXXXXXX to a single Dial(${EXTEN}) command.

We need to be able to provide a heavy level of user/company customisation down to the number level. That’s why when a user dials a number, we need to firstly #include a dial plan that may block certain numbers as a priority, before allowing them to dial anywhere. Something like this…

[c_user]
#include “blocked.conf”
#include “everyone-else.conf”

Then the way to handle that is to store all of your ‘internal’ extensions in an external database (ie - MySQL) and use that as your evaluation on what to do. Either by using the built-in MySQL command or by using an AGI to an external script. This way you may disseminate between what is an internal number and what is an external number (based on presence in the database) and branch in your extensions logic appropriately.

All very much doable, just stop and think about it for a minute. Also, it helps if you think through and state all of your requirements up front, as opposed to going through the ‘peel the onion’ approach to systems design…

You really do fight every inch.

[quote=“dgarstang”]What do I want to do after the _X matches? Go back and start processing again and look for something else that matches.
[/quote]

It seems to me that MuppetMaster’s (btw, great name) routine can do that, you just do the matching in the macro. His switch/case is doing additional matching in the macro. Additionally I suppose (haven’t tried this) you could do a global match in contextA causing you to execute a macro so you execute the macro’s ‘s’ extension (you always execute ‘s’ when you enter a macro) then goto an extension in contextB based on the dialed extension. The thing I am not sure of is if you can jump out of a macro to a context with a goto. But if not, do the matching in the macro.

Yes, it is possible to jump out of a Macro with a Goto. There are many ways to skin this cat…

I’m thinking I may just put this in extensions.conf

[from-phone]
exten => _X,1,Agi(dialplan.agi)

and do everything from a python agi script. Any consequences or known limitations of doing that? One thing I just noticed that was when I placed a PSTN call to a recorded message we use for testing, the audio quality starts out low, goes up and down a few times, got disconnected once, and I even got ringback a few seconds after the call answered. Then the call seems to stabilise. I wonder why it’s doing this? This never happend when the dial was executed from the extensions.conf.

[quote=“dgarstang”]I’m thinking I may just put this in extensions.conf

[from-phone]
exten => _X,1,Agi(dialplan.agi)

and do everything from a python agi script. Any consequences or known limitations of doing that?[/quote]

None come to mind. Although I would recommend using FastAGI:

voip-info.org/wiki-Asterisk+FastAGI

While making a call to a daemon that may maintain the database connections. As of course a database open is an expensive transaction for any database. I have used Java (asterisk-java.sourceforge.net/) to do this, and PHP/Perl for other applications, never Python. But it is about personal choice more than anything.

I have no difference if I dial via an AGI or an Asterisk extensions.conf/ael. Not sure how there could be a difference in audio quality, as the same underlying code is used for the Dial cmd regardless of how it is invoked.

FastAGI… I took a look at the example Fast AGI server. It’s a perl script that basically opens a socket and listens on a port. Not a very scalable solution. It needs to be able to fork/spawn a new thread for each incoming request.

I was thinking… your agi daemon could read the entire database, stick it in memory (as long as it isn’t too big) and reference that. Most transactions are going to be reads anyway. In the event you need to update the in memory copy, send the process a system signal and have it perform another refresh. :smile:

There’s defintely a problem with the way AGI is processing the Audio. Not good. Getting ringback after a call picks up is weird. Unfortunately it hasn’t happened again or I’d get an ngrep trace of the SIP packets.

That is true for that example maybe, but an AGI may be written in virtually anything, including ‘C’. So, the FastAGI is scalable depending on what you put on the other end.

Yes, that is one way to do it.

Strange, never seen it before.