Tag Archive for 'asterisk'

Asterisk: count active calls on certain peers

Let’s imagine that you have a number of peers – both internal users and trunks with VoIP providers.
And you need to count active calls on trunks only. Or even on trunks with some concrete provider, but not the total ‘core show calls’. As an example, you may need to pass that integer to Zabbix.

root@pbx:~# asterisk -C /etc/asterisk/asterisk.conf -rx 'sip show inuse' 
Setting max files open to 1000
* Peer name               In use          Limit           
104                       0/0/0           10              
107                       0/0/0           10              
100                       0/0/0           10                            
voip-isp-london1          1/0/0           6      
voip-isp-london2          2/1/0           6      
root@pbx:~# 

In fact, all magic is done with grep and especially awk tool. Firstly, you need to grep ‘voip-isp’, then extract the second column (is done with awk ‘{print $2}’ ) and then extract the first digit from three ones (e.g. 2 from 2/1/0).
At this point, you’ll get a list of integers, one per line, corresponding to number of active calls on each grepped trunk.
Now it’s time to summarize them, and the best way to do it is also awk! (is done with awk -F\/ ‘{sum += $1} END {print sum}’ )

root@pbx:~# asterisk -C /etc/asterisk/asterisk.conf -rx 'sip show inuse' | grep voip | awk '{print $2}' | awk -F\/ '{sum += $1} END {print sum}'
3

Asterisk 13: list of modules to be used

This list is not as short as it could be. But it still took much time to form it.


[modules]

autoload=no

preload => res_http_websocket.so

load => app_cdr.so
load => app_dial.so
load => app_mixmonitor.so
load => app_playback.so
load => app_stack.so
load => app_verbose.so
load => bridge_simple.so
load => cdr_adaptive_odbc.so
load => cdr_odbc.so
load => chan_bridge_media.so
load => chan_rtp.so
load => chan_sip.so
load => codec_a_mu.so
load => codec_g722.so
load => codec_resample.so
load => codec_ulaw.so
load => format_sln.so
load => format_wav.so
load => func_callerid.so
load => func_cdr.so
load => func_channel.so
load => func_global.so
load => func_periodic_hook.so
load => func_strings.so
load => pbx_ael.so
load => res_ael_share.so
load => res_agi.so
load => res_clialiases.so
load => res_format_attr_celt.so
load => res_format_attr_opus.so
load => res_format_attr_silk.so
load => res_format_attr_siren14.so
load => res_format_attr_siren7.so
load => res_format_attr_vp8.so
load => res_http_post.so
load => res_limit.so
load => res_odbc_transaction.so
load => res_odbc.so
load => res_rtp_asterisk.so
load => res_rtp_multicast.so
load => res_security_log.so

CentOS 7.2.1511 and Asterisk 13.1: max open files problem

Asterisk 13.1 (running under CentOS 7.2.1511, maybe some other Asterisk versions too) has a problem: setting ‘maxfiles’ in asterisk.conf does not matter.
So, one day, your Asterisk may stop processing new calls under high load, and as the max opened files limit is reached, you will even have no opportunity to enter the Asterisk CLI.

The /var/log/asterisk/messages (or Asterisk CLI, if you’ve been already logged in before reaching the max open files limit) will be filling with messages like these:

[Feb 13 16:47:00] WARNING[9283] acl.c: Cannot create socket
[Feb 13 16:47:00] WARNING[9283] rtp.c: Unable to allocate RTCP socket: Too many open files
[Feb 13 16:47:00] WARNING[14732] acl.c: Cannot create socket
[Feb 13 16:47:00] WARNING[14732] channel.c: Channel allocation failed: Can't create alert pipe! 
Try increasing max file descriptors with ulimit -n

As a workaround, you may change the soft and hard limit for the Asterisk process on the OS level. But first of all let’s check how many files are allowed for Asterisk to be opened:

voip-b2b01 ~ # cat /proc/`pidof asterisk`/limits
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             15693                15693                processes 
Max open files            1024                 1024                 files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       15693                15693                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us        

So, you see the line with ‘1024’ value, in spite of our setting in asterisk.conf:

Max open files            1024                 1024                 files     

Let’s fire! CentOS has a nice tool called prlimit. Use it:

prlimit --pid `pidof asterisk` --nofile=8192

Now let’s check again:

voip-b2b01 ~ # cat /proc/`pidof asterisk`/limits
Limit                     Soft Limit           Hard Limit           Units     
...
Max open files            8192                 8192                 files     
...

CentOS 7.2 uses Systemd, so it’s wise to edit Asterisk-related configuration file.
We check the /etc/systemd/system/multi-user.target.wants/ directory and see an ‘asterisk.service’ file there, which is a symlink in fact, leading to /usr/lib/systemd/system/asterisk.service:

voip-b2b01 ~ # ls -l /etc/systemd/system/multi-user.target.wants/
total 0
lrwxrwxrwx  1 root root 40 июл 14 13:09 asterisk.service -> /usr/lib/systemd/system/asterisk.service
lrwxrwxrwx. 1 root root 38 сен 15  2015 auditd.service -> /usr/lib/systemd/system/auditd.service
lrwxrwxrwx. 1 root root 41 июн 28 14:44 bacula-fd.service -> /usr/lib/systemd/system/bacula-fd.service
lrwxrwxrwx. 1 root root 39 сен 15  2015 chronyd.service -> /usr/lib/systemd/system/chronyd.service
lrwxrwxrwx. 1 root root 37 сен 15  2015 crond.service -> /usr/lib/systemd/system/crond.service
lrwxrwxrwx. 1 root root 42 сен 15  2015 irqbalance.service -> /usr/lib/systemd/system/irqbalance.service
lrwxrwxrwx. 1 root root 41 июн 28 12:33 nfs-client.target -> /usr/lib/systemd/system/nfs-client.target
lrwxrwxrwx. 1 root root 39 июн 28 12:49 oddjobd.service -> /usr/lib/systemd/system/oddjobd.service
lrwxrwxrwx. 1 root root 40 сен 15  2015 remote-fs.target -> /usr/lib/systemd/system/remote-fs.target
lrwxrwxrwx. 1 root root 39 сен 15  2015 rsyslog.service -> /usr/lib/systemd/system/rsyslog.service
lrwxrwxrwx  1 root root 40 июл 14 13:02 sendmail.service -> /usr/lib/systemd/system/sendmail.service
lrwxrwxrwx  1 root root 41 июл 14 13:02 sm-client.service -> /usr/lib/systemd/system/sm-client.service
lrwxrwxrwx. 1 root root 36 сен 15  2015 sshd.service -> /usr/lib/systemd/system/sshd.service
lrwxrwxrwx. 1 root root 36 июн 28 12:49 sssd.service -> /usr/lib/systemd/system/sssd.service
lrwxrwxrwx. 1 root root 44 июн 28 14:19 zabbix-agent.service -> /usr/lib/systemd/system/zabbix-agent.service

Just uncomment/edit the parameter LimitNOFILE. And I advise you to uncomment/edit the Restart=always line to let Systemd control the Asterik is running (now you need not use Monit). You will have such a configuration:

voip-b2b01 ~ # grep -vE '^$|^;|^#' /usr/lib/systemd/system/asterisk.service 
[Unit]
Description=Asterisk PBX and telephony daemon.
After=network.target

[Service]
Type=simple
Environment=HOME=/var/lib/asterisk
WorkingDirectory=/var/lib/asterisk
User=asterisk
Group=asterisk
ExecStart=/usr/sbin/asterisk -f -C /etc/asterisk/asterisk.conf
ExecStop=/usr/sbin/asterisk -rx 'core stop now'
ExecReload=/usr/sbin/asterisk -rx 'core reload'
LimitNOFILE=8192:8192
Restart=always

PrivateTmp=true

[Install]
WantedBy=multi-user.target

Don’t forget to re-read settings by systemd:

systemctl daemon-reload

… and now it’s time to restart Asterisk:

systemctl restart asterisk.service

Well, at this point we’ve changed the max open files limit for the Asterisk process manually and changed the Systemd Asterisk config, hoping that it will start now with the 8192 max open files limit.

If you’re interested in how many files are currently opened by your Asterisk, you may try:

voip-b2b01 ~ # lsof -p `pidof asterisk` | wc -l
956

Asterisk 13: chan_sip sip_write Can’t send 10 type frames with SIP write

Centos 7
Asterisk 13.1

Noticed a WARNING which filled Asterisk’s messages logfile:
bridge_simple_vs_bridge_softmix

To get rid of it, use bridge_softmix.so module instead of bride_simple.so.
Thanks to Lenar Daminov from our team for research.

UPD: https://community.asterisk.org/t/bridge-simple-and-bridge-softmix-difference/69193

jcolp, Asterisk developer:

The bridge_softmix module is more heavy weight as it gets data from each channel, transcodes it into signed linear, mixes it at an interval, and then sends it out. Even for 2 channel bridges it will do this. The bridge_simple module simply exchanges data back and forth without mixing. Frame type 10 is comfort noise which is not currently supported by Asterisk.

Asterisk 11: some required modules

Asterisk 11, modules, which have to be loaded for other basic modules to work properly.

preload => res_http_websocket.so	; for chan_sip.so load
preload => res_speech.so		; for res_agi.so load
preload => res_agi.so			; for app_stack.so load
preload => res_monitor.so		; for app_queue.so correct load
preload => res_ael_share.so		; for pbx_ael.so correct load // also works without this,
                                        ; but WARNING while loading

Asterisk: ODBC configuration files relations

https://wiki.asterisk.org/wiki/display/AST/Getting+Asterisk+Connected+to+MySQL+via+ODBC
https://wiki.asterisk.org/wiki/display/AST/Configuring+res_odbc

odbcinst.ini
===================

[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib/odbc/libmyodbc.so
Setup = /usr/lib/odbc/libodbcmyS.so
FileUsage = 1

odbc.ini
===============

[asterisk-connector]
Description	= MySQL connection to 'asterisk' database
Driver = MySQL
Database = asterisk
Server = localhost
Port = 3306
Socket = /var/lib/mysqld/mysqld.sock

res_odbc.conf
====================

[asterisk]
enabled => yes
dsn => asterisk-connector	// points to DB connection in odbc.ini
username => asterisk
password => welcome
pooling => no
limit => 1
pre-connect => yes

cdr_adaptive_odbc.conf
==============================

connection = asterisk // The database connection to be used. This is a reference 
                      // to the configured connection in res_odbc.conf. This field is required.
table = // The table name. This field is required.

Asterisk: Queue statistics

As it’s said in queues.conf:

  ; If set to yes, the following variables will be set
  ; just prior to the caller being bridged with a queue member
  ; and just prior to the caller leaving the queue
  ; QUEUENAME name of the queue
  ; QUEUEMAX maxmimum number of calls allowed
  ; QUEUESTRATEGY the strategy of the queue;
  ; QUEUECALLS number of calls currently in the queue
  ; QUEUEHOLDTIME current average hold time
  ; QUEUECOMPLETED number of completed calls for the queue
  ; QUEUEABANDONED number of abandoned calls
  ; QUEUESRVLEVEL queue service level
  ; QUEUESRVLEVELPERF current service level performance
  ;
  ;setqueuevar=no

So, add ‘setqueuevar=yes’ to each queue definition in queues.conf and then modify your dialplan after execution of the Queue application:

  Queue(${EXTEN},t,,,25);

  // to enable Queue statistics
  NoOp(${QUEUE_VARIABLES(${EXTEN})});

  NoOp(QUEUESTRATEGY is ${QUEUESTRATEGY});
  NoOp(QUEUECALLS is ${QUEUECALLS});
  NoOp(QUEUEHOLDTIME is ${QUEUEHOLDTIME});
  NoOp(QUEUECOMPLETED is ${QUEUECOMPLETED});
  NoOp(QUEUEABANDONED is ${QUEUEABANDONED});
  NoOp(QUEUESRVLEVEL is ${QUEUESRVLEVEL});
  NoOp(QUEUESRVLEVELPERF is ${QUEUESRVLEVELPERF})

Console output:

  Executing [007@inc:33] NoOp("007@inc-1658;2", "0") in new stack
  Executing [007@inc:34] NoOp("007@inc-1658;2", "QUEUESTRATEGY is ringall") in new stack
  Executing [007@inc:35] NoOp("007@inc-1658;2", "QUEUECALLS is 0") in new stack
  Executing [007@inc:36] NoOp("007@inc-1658;2", "QUEUEHOLDTIME is 6") in new stack
  Executing [007@inc:37] NoOp("007@inc-1658;2", "QUEUECOMPLETED is 12778") in new stack
  Executing [007@inc:38] NoOp("007@inc-1658;2", "QUEUEABANDONED is 34844") in new stack
  Executing [007@inc:39] NoOp("007@inc-1658;2", "QUEUESRVLEVEL is 10") in new stack
  Executing [007@inc:40] NoOp("007@inc-1658;2", "QUEUESRVLEVELPERF is 54.6") in new stack

Asterisk: asterisk dead but subsys locked

Problem: After successful installation from source (CentOS 6.5 x86_64, Asterisk 11.12.1) you get:

root@twt [~]# service asterisk status
asterisk is stopped
root@twt [~]# service asterisk start
Starting asterisk:
root@twt [~]# service asterisk status
asterisk dead but subsys locked
root@twt [~]# asterisk -rv
asterisk: error while loading shared libraries: libasteriskssl.so.1: cannot open shared object file: No such file or directory

Solution:
ln -s /usr/lib/libasteriskssl.so.1 /usr/lib64/libasteriskssl.so.1

Brute your trunks, dial out

A small snippet of dialplan how to dial if some trunk is not reachable.

Imagine, we have two SIP-trunks to dial out – [trunk1] and [trunk2]. You have to set ‘qualify=yes’ for both, otherwise this method will not work.
We’ll use the SIPPEER function with the ‘status’ argument:

; Func SIPPEER
exten => 401040,NoOp
    same => n,NoOp( [trunk1] SIPPEER info: ${SIPPEER(trunk1,status)})
    same => n,NoOp( ;===================================== )
    same => n,NoOp( [trunk2] SIPPEER info: ${SIPPEER(trunk2,status)})
    same => n,NoOp( ;===================================== )
    same => n,GotoIf($[${SIPPEER(trunk1,status)}= "OK"]?t1dial:t2)
    same => n(t1dial),Dial(SIP/trunk1/${EXTEN},5)
    same => n,Hangup
    same => n(t2),NoOp( [trunk1] is UNREACHABLE, trying [trunk2] in 1 second ... )
    same => n,Wait(1)
    same => n,GotoIf($[${SIPPEER(trunk2,status)}= "OK"]?t2dial:hang)
    same => n(t2dial),Dial(SIP/trunk2/${EXTEN},5)
    same => n,Hangup
    same => n(hang),Playback(have-a-rest)
    same => n,Hangup

Asterisk: round-robin dial out through trunks

Imagine that we have 3 trunks for dial out and we must balance outgoing calls in random order. This could be done with the RAND function. Module func_rand.so must be compiled and loaded.

sip.conf:

[trunk1](trunk_preset)
host=10.10.10.11

[trunk2](trunk_preset)
host=10.10.10.12

[trunk3](trunk_preset)
host=10.10.10.13

extensions.conf:

exten => _79XXXXXXXXX,1,NoCDR()
    same => n,Dial(SIP/trunk${RAND(1,3)}/${EXTEN})
    same => n(hang),Hangup()

You may say – well, OK, but what if my trunks are named not like [trunk1], [trunk2], [trunkN] and I can not substitute the last symbol in Dial application?
In this case we can write a list of trunk names (which you configured already in sip.conf) in txt file, for example rrtrunks.txt:

teliasonera-out
deutschetelekom-out
level3-out

Ensure that a ‘sort’ command is available in your *NIX system. Usually it’s a part of coreutils. Older versions don’t suit us, because they don’t have the ‘-R’ flag which means sort randomly. Newer versions have.

Then load func_shell.so and use it in your dialplan. It can execute a shell command and use its output in dialplan.

exten => _79XXXXXXXXX,1,NoCDR()
    same => n,Dial(SIP/${SHELL(sort -R /etc/asterisk/rrtrunks.txt | head -1)}/${EXTEN},20)
    same => n,Hangup()

It means that we sort randomly our list of trunks and get the first one each time.