24.12.2019

Kamailio. uac_auth. cseq. t_relay fail.

чтобы увеличивать cseq нужно использовать модуль диалог.

modparam(“dialog”, “track_cseq_updates”, 1)

если вы используете в failure_route uac_auth, то учите что при несовпадении realm в запросе на авторизацию и в функции uac_auth вы получите ошибку

ERROR: {1 62503 INVITE } tm [t_fwd.c:1717]: t_forward_nonack(): no branches for forwarding
ERROR: {1 62503 INVITE } tm [tm.c:1679]: _w_t_relay_to(): t_forward_noack failed

А в 2016 был баг на эту тему в kamailio. сейчас видимо не баг.

19.12.2019

WEBRTC2SIP. KAMAILIO. RTPENGINE. CENTOS 7.

Полная статья по инсталляции webrtc2sip на centos 7 здесь. А тут видео.

В качестве основы эту статью и компиляцию вручную. В целом компиляция особых проблем не вызвала. Пакеты все которые надо ставятся.

Проблема возникла при инсталляции в качестве сервиса.

а) не стал разбираться с правами и запускаю от root,
б) необходимо убрать из rtpengine.services параметры из окружения,

Было:

ExecStart=/usr/sbin/rtpengine --config-file=${CFGFILE} --interface=${INTERFACE} --listen-ng=${LISTEN_UDP} --log-facility=${LOG_FACILITY} --log-level=${LOG_LEVEL}

Стало:

ExecStart=/usr/sbin/rtpengine --pidfile /run/rtpengine.pid --config-file /etc/rtpengine/rtpengine.conf --table 0

в) учесть имена pid файла, он должен совпадать в /etc/rtpengine/rtpengine.conf , /etc/sysconfig/rtpengine , rtpengine.service – последний файл можно найти командой systemctl status rtpengine.service.

Помощь с ошибками:

webrtc console:  Called with SDP without DTLS fingerprint. - для моей версии rtpengine, необходимо было использовать ICE=force, без этого флага rtpengine не добавлял fingerprint в SDP. возможно в новых версиях rtpengine всё уже в порядке. 

15.12.2019

FreePBX AMI Events duplicate. queue. agents.

По умолчанию, freepbx создают агентов в очереди в качестве локальных каналов local/1000-ext/n , где /n означает отключение автоматизации внутренних каналов, по этому создается по два канала в каждой очереди и видимо с обоих приходит уведомление. В общем если заполнять агентов с префиксом S например S1001,0, уведомления приходят ровно по одному на очередь как и должно быть. Всем спасибо. Я кстати не могу зарегаться на основном сайте, не показывает капчу… Тематика Астериска последнее время близка. кто знает может чем смогу помочь.

12.12.2019

callback+freepbx+AMD

Схема работы такая:

Любой разрешенный ip звонит на DID номер pbx, станция перезванивает с DID номера и соединяет с внутренним абонентом) показывая в качестве callerid номер на который осуществляется дозвон.

Особенности: минимум вмешательства в код freepbx чтобы можно было использовать весь функционал станции.

У вас уже установлена: Freepbx, callback модуль, правильно настроены callback и trunk в интерфейсе freepbx

Всё что нам нужно это добавить передачу переменной в callback модуль:

//define the args for Originate
$channel = "Local/".$callback_number."@from-internal";
$exten = $callback_exten;
$context = $callback_context;
$priority = $callback_priority;
$timeout = $callback_timeout;
$callerid = $callback_callerid;
$variable = "__MYVAR4=$callback_number";
$account = "";
$application = "";
$data = "";

затем поймать её в extension_custom.conf

[macro-dialout-one-predial-hook]
exten => s,1,set(CALLERID(all)=${MYVAR4})

[macro-AMD1]
exten => s,1,noop("Check of answering machine")
exten => s,n,background(silence/1)
exten => s,n,AMD()
exten => s,n,NoOp("AMD STATUS IS :"${AMDSTATUS}"…CAUSE:"${AMDCAUSE})
exten => s,n,Set(CDR(userfield)=${AMDSTATUS}|${AMDCAUSE})
exten => s,n,GotoIf($[${AMDSTATUS}=HUMAN]?human:mach)
exten => s,n(mach),Hangup()
exten => s,n(human),noop(This is Human continue)

How to use callback calls at freepbx

  1. Create callback application in menu. It will make you possible to send calls from callback to any registered extension \ Ring groups \ Queues \ IVR or something else.  In CallerID field you should set “${FROM_DID}” to send calls from your DID number. 
  1. Create Trunk for making outbound calls with AMD it may be any trunk but you should add “TM(AMD1)” in Dial options.
  2. Create inbound route for receive call from any IP and to specific DID number: you have example here in interface with number 55555. Choose destination as callback application created at step 1. 
  3. Create outbound route for route calls making by your freepbx (not only from callback app). You should set Dial Patterns to avoid making call to destinations that you don’t want to call. 
  4. Apply changes. That is all you need in web interface. 

4.12.2019

постоянный сетевой маршрут windows l2tp переподключение

route add -p  185.63.144.1 10.0.0.100 METRIC 1 if 31

Чтобы узнать номер интерфейса: route print

29.11.2019

AMI FREEPBX NAMI SYSLOG NODEJS

В этом проекте нам нужно сохранять различные события в очередях Астериска через nodejs библиотеку NAMI. Сложности тут на первый взгляд только одна, это создания таблиц для сохранения событий. На самом деле нет, есть еще задача сохранения неудачного запроса, есть задача выполнения асинхронного запроса, чтобы не скрипт не тормозил.

В проект включены файлы:
tables.sql – который создает базу данных asterisk_logs и несколько табличек в ней,
table-ami-events.ods – excel файл с описанием событий по столбцам.

  1. создаем БД и таблички tables.sql,
  2. устанавливаем “npm install nami mysql modern-syslog”
  3. добавляем пользователя monit в manager_custom.conf
  4. прописываем учетные данные для mysql и asterisk manager в массивы db_config и namiConfig.
  5. Запускаем скрипт nami.js и если модули nodejs установлены верно, то скрипт запустится даже если у вас нет астериска и базы данных.

особенностью этого скрипта является то, что даже при пропадании подключения к mysql он будет пытаться реконнектится, при пропадании к астериску тоже. И если если подключение к астериску есть, а к mysql нет, то он будет сохранять готовые для импорта запросы в syslog.

фалы проекта можно скачать тут

29.11.2019

certbot ssl certificate for issabel manual installation

  1. install certbot (was installed by issabel)
  2. comment rewrite engine in /etc/httpd/issabel.conf
  3. add virtual host file “issabelmanual.conf” with 80 port into /etc/httpd/conf.d
<VirtualHost *:80>
 <Directory "/var/www/html">

 </Directory>
</VirtualHost>

3. restart httpd: systemctl restart httpd
4. run certbot and answer to questions
5. certbot will add new sertificate to your ssl.conf file and comment old ssl lines in this file
6. uncomment at step 2.
7. restart httpd: systemctl restart httpd.
8. add to cron renew certificate every month by command “crontab -e”
“@monthly certbot renew”

26.11.2019

mysql optimization

Задача отображать данные из таблицы которая превышает 100 млн записей. Опции которые нужно проверить. Для отображения последних данных используется скрипт:

  1. Создание индекса НЕ на всю длину,
  2. Создание индексов для двух колонок,
  3. Для уменьшения места можно использовать компрессию для таблицы, сжимает – будь здоров, но потеря в производительности.
  4. Ограничение времени для выполнения конкретного запроса через /*+ MAX_EXECUTION_TIME($TIMEOUT) */  где $TIMEOUT в микросекундах.
  5. Изменение параметров кешей и прочего значимых изменений не дали.
  6. Создание и управление вторым сервером на компьютере для проведения тестирования при помощи mysqld_multi.
  7. create table new like current > rename current to old_tmp, new to current > select into tmp.csv where time > (2 days) > load data from tmp.csv into current > rm csv.

21.11.2019

Freepbx using any CAllerID display name as callerID(num) when making external calls

В рамках freepbx вы не можете установить callerid name (display) как вы хотите, вы всегда будете видеть тот display name который установили при создании Extension.

Чтобы исправить эту несправедливость, добавляем в extension_custom.conf

[macro-dialout-trunk-predial-hook]
exten => s,1,Noop(Number translation)
exten => s,n,Set(MYFROM=${PJSIP_HEADER(read,From)})
exten => s,n,set(MYFROM=${CUT(MYFROM, ,1)})
exten => s,n,set(MYFROM=${REPLACE(MYFROM,\")})
exten => s,n,Noop(HEADER - ${MYFROM})
exten => s,n,Set(CALLERID(number)=${MYFROM})

после этого при исходящих звонках через транки, вы будете видеть тот АОН который вы выставить в CAller ID name в своем софтфоне.

19.11.2019

Asterisk Click2Call API

  1. Готовый скрипт для вызовов между extension и внешним номером, а также для запуска любого диалплана и передачи ему параметров. Использовалась библиотека https://github.com/chan-sccp/PAMI это форк самой популярной библиотеки от marcelog/PAMI. Используется потому, что в ней исправлена ошибка при использовании CommandAction. в оригинальной библиотеке она будет выдавать read timeout. Скрипт выдает статус оригинации в json формате и unqueid. техническое задание в конце кода.
ini_set('display_errors', 0);
require __DIR__ . '/vendor/autoload.php';

use PAMI\Client\Impl\ClientImpl;
use PAMI\Listener\IEventListener;
use PAMI\Message\Event\EventMessage;
use PAMI\Message\Action\OriginateAction;
use \PAMI\Message\Event\NewchannelEvent;

class A implements IEventListener
{
    public $result;

    public function handle(EventMessage $event)
    {

        if ($event instanceof \PAMI\Message\Event\NewchannelEvent) {

            $this->result = $event->getUniqueID();
            return $this->result;
        }


    }
}

$agent          = $_GET['agent'];
$extension      = $_GET['extension'];
$destination    = $_GET['destination'];

while ($agent && $extension) {
    echo "No agent and extension possible!";
    exit;
}

include "config.php";

        $a = new ClientImpl($options);
        $a->open();
        $ClassA = new A();
        $a->registerEventListener($ClassA);

        while ($agent && $destination) {

            echo "Agent && Destination";
            $result = makecallagent($a,$agent,$destination);
            $arr = array('success' => false, 'errormsg' => $result);

            if ($result === true)
                $arr = array('success' => $result,'errormsg' => NULL, 'uniqueid' =>  $ClassA->result);


            echo json_encode($arr);

            $a->close();
            exit;
        }

        while ($extension && $destination) {

            $result = makecall($a,$extension,$destination);

            $arr = array('success' => false, 'errormsg' => $result);

            if ($result === true)
                $arr = array('success' => $result,'errormsg' => NULL, 'uniqueid' =>  $ClassA->result);


            echo json_encode($arr);

            $a->close();
            exit;
        }

        echo "No extension\agent and destination correctly passed";
        exit;


function makecall($a,$source,$number) {

        $originateMsg = new OriginateAction("PJSIP/$source");
        $originateMsg->setContext('from-internal');
        $originateMsg->setPriority('1');
        $originateMsg->setExtension("$number");
        $res = $a->send($originateMsg);

        if ($res->isSuccess()) return true;   //return tru if originating success
        return $res->getKeys()['message'];    //otherwise return error message

}

function makecallagent($a,$source,$number) {

        $originateMsg = new OriginateAction("Local/28@queuemetrics");
        $originateMsg->setContext('queuemetrics');
        $originateMsg->setPriority('1');
        $originateMsg->setVariable('AGENTCODE',$source);
        $originateMsg->setVariable('QDIALER_QUEUE','outqueue');
        $originateMsg->setVariable('EXTTODIAL',$number);

        $originateMsg->setExtension("28");
        $res = $a->send($originateMsg);

        if ($res->isSuccess()) return true;   //return tru if originating success
        return $res->getKeys()['message'];    //otherwise return error message
}