📜 ⬆️ ⬇️

Asterisk + LUA: quick start

Over the last year several articles about using lua dialplan in asterisk ( one , two , three , four ) appeared on Habré. This is quite an interesting way of writing flexible and powerful dialplans. But to try this way of writing dialplans, you need to spend some amount of time: install the necessary libraries, rebuild the asterisk with the necessary options.

In addition, many asterisk users have a different level of training: someone is closer to system administration or even to traditional telephony than to programming. Plus, the specificity of telephony - it is better once again with unfamiliar experiments not to load working systems, but to carry out tests and experiments on your laptop - you have to clutter up the system. In general, there are many reasons to "postpone until later."

In this article I want to show everyone and those who work with asterisks how, using the docker, you can quickly feel the taste of flexible lua scripts. And then decide whether to use it further in practice or not. (Who is not interested in reading, and it is interesting to watch and listen - at the end of the text is a 6-minute video with the main points and results.)
')


Introductory word


As part of working on several of my projects, following the current trend of packing everything into containers, I prepared the image of astolua (asterisk + lua). The Dockerfile contains commands for installing asterisk 11, lua 5.1, luarocks (package manager for lua), luamongo (driver for accessing mongodb), some packages of lua rocks. You can later on in the docker-astolua repository take only what is useful for you and collect your workhorse.

Of course, the advantage of the docker is the ability to download an image, perform tests, experiment tests, and then delete images, leaving your operating system clean and in a familiar manner.

Based on the astolua image, we will create our working image in which we will use the asterisk configuration test files and the dialplan on lua.

Training


We need a docker. If you do not have it installed, then please install the docker first ( official documentation , article on Habré ).

We also need git ( install git )

Also immediately note that my working system is Ubuntu 14.04. If you are using a different Linux, then there should be no differences in the teams, but the nuances are not excluded.

Download astolua image


Tighten the image (attention, the image will be downloaded from the hub.docker.com repository ~ 600MB in size).

docker pull antirek/astolua 


Sample


Cloning docker-astolua-sample is a pre-prepared set of files for this article.

 git clone https://github.com/antirek/docker-astolua-sample.git cd docker-astolua-sample 


Now let's look at sample and look at the contents of the directory.

Dockerfile file

The file to build our working image. In it we indicate that we take astolua as a basis. Then we add the startup script after_start.sh, which will be executed when the container is started. In the console, where we run the container, the asterisk console log will be displayed.

Build file

Inside the file, the docker team is building a sample image from our Dockerfile.
 docker build -t "astolua:sample" . 


Run file
Inside the file is the docker's command to launch the container based on the sample image with the configuration of the resources it needs.

 docker run \ -v /etc/localtime:/etc/localtime:ro \ -v $(pwd)/store/etc/asterisk:/etc/asterisk \ -v $(pwd)/store/var/log/asterisk:/var/log/asterisk \ -v $(pwd)/store/var/menu:/var/menu/ \ --net=host \ -i -t "astolua:sample" 


Folder store
The store folder contains the asterisk configuration files (such as those usually found in / etc / asterisk) and folders for logs and voice menus.

The run command is the most interesting, because the required resources for the container are indicated here. For example, with the -v $ (pwd) / store / etc / asterisk: / etc / asterisk option, we specify that the configuration files from our store folder should appear inside the container in its place in / etc / asterisk.

Why are the commands in the files? It is convenient to edit the commands in the files, because this speeds up time to test changes in teams with different options, and all changes will fall under version control. And it is also convenient to transfer the options to docker-compose later, if the image will be shared with others.

Let's go back to the console.

Make an image of astolua: sample (in the directory where we have cloned docker-astolua-sample)
 ./build 


Run asterisk (if you have an asterisk or another service that occupies port 5060 already running on the machine, then it is better to stop it)
 ./run 


The asterisk download log should crash into the console. You can test the connection.

In the asterisk configuration file sip.conf there are two subscribers 101 and 102 (password 1234), and in the queues.conf file the queue 1234, to which these two subscribers are added. Set up your softphone or hardphone for 101 subscribers and try to make a call to subscriber 102. (There are no trunks to connect to external voip services or settings of any hardware, so we will test dialplan on local calls). Information about the call between subscribers should appear in the console of the asterisk.

Do subscribers work, pass calls? Ok, so the asterisk in the docker is working as it should.

Dialplan lua


Dialplan lua is in the file extensions.lua. In the asterisk configuration files in the store / etc / asterisk folder there is an example of a working lua dialplan.

In this file, variable extensions and hints must be correctly described (in lua terminology, these are “tables”).

The extensions table contains contexts and corresponding extensions. Just like in a traditional dialplan. But each extension is processed by its own function, in which you can already do anything on lua, while interacting with the asterisk through the app and channel tables.

The simplest example

 extensions = { ["internal"] = { ["_1XX"] = function (context, extension) -- do something -- app.dial('SIP/'..extension); -- do something again end; } } 


It can be seen that the dialplan application Dial is available through the app, it takes all the same parameters as in the traditional dialplan. Through the app, all dialplan applications are available.

The channel variable gives access to channel variables. So, for example, we get dialstatus.

 extensions = { ["internal"] = { ["_1XX"] = function (context, extension) -- do something -- app.dial('SIP/'..extension); local dialstatus = channel["DIALSTATUS"]:get(); app.noop('dialstatus: '..dialstatus); end; } } 


You can change extensions.lua and then the command in the asterisk CLI module reload pbx_lua.so to reread extensions.lua. Asterisk will check the lua syntax, and if everything is ok, then it will be loaded for execution - you can test the changes.

What else can you do in the lua dialplan?

For example, flexibly handle dialstatus, which will be returned by the Dial Dialplan function. No more reinventing these Goto (s - $ {DIALSTATUS}, 1) , now you can write a status check

 extensions = { ["internal"] = { ["_1XX"] = function (context, extension) app.dial('SIP/'..extension); local dialstatus = channel["DIALSTATUS"]:get(); if dialstatus == 'BUSY' then -- do something elseif dialstatus == 'CHANUNAVAIL' then -- do another thing end; end; } } 


In the example of extensions.lua there is an example of a simple ivr: by calling 200, you will hear an entry from the file / var / menu / demo and you can move on by pressing 1 or 2.

 local ivr = function (context, extension) app.read("IVR_CHOOSE", "/var/menu/demo", 1, nil, 2, 3); local choose = channel["IVR_CHOOSE"]:get(); if choose == '1' then app.queue('1234'); elseif choose == '2' then dial('internal', '101'); else app.hangup(); end; end; 


For a person who has written a couple of dozen lines of a traditional dialplan, everything should be familiar here. Plus, the full power of lua and luarocks packages appears. I hope it is obvious that here in the dialplan you can send SMS, email, put data in DB, take data from DB, and DB can be any: mysql, mongodb, redis, etc., make a command call, initiate another call , to make a cool routing of a call on trunks, etc., not forgetting, of course, that this all works as part of an asterisk, and it is better to solve all the “hard” tasks separately.

What's next?


I suggest:


I hope this article will be useful for a quick start, and you will find one free winter evening and try this way of writing dialplans.



Errors? Patches? Questions? Please write.

Source: https://habr.com/ru/post/271939/


All Articles