Новости
Обзоры и тесты
Техно
Советы
Разное
Главная » Техно

Сравниваем конфигурации Freeswitch и Asterisk для одной задачи

Добавлено на 27.02.2019 – 09:45

Для чемпионата мира в России, который прошёл в 2018 году, нужно было решить задачу авторизации пользователей для услуги Wi-Fi при помощи звонка на телефонный номер как один из способов авторизации. Для решения использованы аналогичные конфигурации Freeswtich и Asterisk.

Смысл в том, что пользователь вводит номер телефона своего смартфона\планшета\компьютера через веб-форму авторизации в Wi-Fi сети, далее, пользователь выбирает каким способом он подтвердит, что это действительно его мобильный номер: при помощи отправки SMS-сообщения или звонком на номер телефона, где ему должна проиграться голосовая подсказка о успешности\неуспешности авторизации, в зависимости от языка интерфейса(русский, английский, французский, немецкий или испанский). Голосовая платформа Asterisk\Freeswith передаёт номер позвонившего серверу авторизации, сервер сверяет телефонный номер полученный через веб-форму с номером, который передала голосовая платформа, в ответ возвращается успешный или неуспешный код. Сообщение должно проигрываться в предответном состоянии до начала тарификации, чтобы абонент не платил деньги за звонок. Так как Asterisk и Freeswitch в этой схеме выполняют функции медиасерверов, будем называть далее их именно так.
Терминация из телефонных сетей на медасерверы работала через два транковых шлюза Eltex SMG1016M, голосовых платформ тоже две: первая Asterisk 15.3.0 установленный на ОС Linux Debian 9.4, вторая FreeSWITCH Version 1.6.20 установленная на ОС Linux Debian 8.10. В июне 2018 FreeSWITCH ещё не поддерживал ОС Linux Debian 9 для «продакшен» режима.
Asterisk и Freeswitch запущены на виртуальных машинах, основные пики нагрузки приходились, когда начинались футбольные матчи.
Главный минус схемы с такой авторизацией – иногда из телефонной сети общего пользования может приходить искажённый номер вызывающего абонента(А-номер), в таком случае пользователь не будет авторизован, хотя правильно указал свои данные. Данная ситуация была замечена у одного сотового оператора для парных номеров: федеральный номер плюс местный городской номер в которых равны последние 7 цифр номера.

Техническая реализация

Создан пул телефонных номеров равный количеству языков – 5, звонки на любой из 5 телефонных номеров по очереди попадает на шлюзы SMG1016: 192.168.25.8 и 192.168.25.9, на каждом из шлюзов созданы транковые направления терминации состоящие из двух транковых групп, по одной на медиасервер (Asterisk и Freeswitch), алгоритм работы направлений для терминации: последовательно вперёд.

Транковое направление SMG

Заметку по маршрутизации на шлюзах Элекс SMG можно найти по данной ссылке.
Оба шлюза подключены к городской АТС, где также создана группа терминации с алгоритмом работы по очереди. Такая схема даёт равномерное распределение нагрузки по шлюзам и медиасерверам.
Когда медиасервер получает вызов, он делает запрос по http на сервер авторизации куда в фомате JSON передаёт номер телефонный позвонившего и телефонный номер для авторизации куда позвонил пользователь:

data={'user_phone': user_phone,'gw_phone': gw_phone}

В ответ сервер передаёт код ответа и результат в формате:

resultCode=1&resultMessage=accepted

Если,

  • resultCode = 1 – проиграть подсказку об успешно авторизации
  • Любой другой код – проиграть сообщение об ошибке

В статье я не буду касаться вопросов инсталляции Asterisk и Freeswtich, рассмотрю только необходимую конфигурации внешнего канала SIP и дайлплана, также скриптов которые делают запрос по http и возвращают результат.

Медиасервер Astersik

IP-адрес=192.168.25.32

Здесь из дайлплана при помощи AGI вызываем внешний скрипт, который сделает запрос на сервер и вернёт результат.

Настройка внешних каналов SIP для приёма трафика от шлюзов, файл /etc/asterisk/sip.conf

[FIFA-1]
type=peer
context=FIFA-IN
host=192.168.25.8 ;Шлюз 1 SMG1016M
insecure=port,invite
disallow=all
allow=ulaw
nat=no
canreinvite=no
use_q850_reason = yes


[FIFA-2]
type=peer
context=FIFA-IN
host=192.168.25.9 ;Шлюз 2 SMG1016M
insecure=port,invite
disallow=all
allow=ulaw
nat=no
canreinvite=no
use_q850_reason = yes

Здесь вызовы с любого из двух шлюзов отправляются в контекст FIFA-IN.
Дайплан Asterisk, файл /etc/asterisk/extensions.ael
Приведу только первые два номера, напомню, что всего языков подсказок 5 и номеров столько же, соответственно.

context FIFA-IN
{
78120002915 => {
        AGI(get-res.py,${CALLERID(num)},${EXTEN:1});
Set(CDR(userfield)=${ANSWER});
NoOp(RES => ${RES});
        switch (${RES}) {
                    case 1:
                    Progress();
                    Playback(/var/lib/asterisk/sounds/fifa/success_readyRUS1,noanswer);
                    Busy(10);
                    Hangup(16);
                  default:
                    Progress();
                    Playback(/var/lib/asterisk/sounds/fifa/Fail_RUS1,noanswer);
                    //Playback(/var/lib/asterisk/sounds/ru/agent-alreadyon,noanswer);
                    Busy(10);
                    Hangup(16);

                };
        };

78120002916 => {                                                                //English
        AGI(get-res.py,${CALLERID(num)},${EXTEN:1});
Set(CDR(userfield)=${ANSWER});
NoOp(RES => ${RES});
        switch (${RES}) {
                    case 1:
                    Progress();
                    Playback(/var/lib/asterisk/sounds/fifa/Success_readyEN1,noanswer);
                    Busy(10);
                    Hangup(16);
                  default:
                    Progress();
                    Playback(/var/lib/asterisk/sounds/fifa/Fail_EN1,noanswer);
                    //Playback(/var/lib/asterisk/sounds/ru/agent-alreadyon,noanswer);
                    Busy(10);
                    Hangup(16);

                };
        };


};

Любой вызов, пришедший со шлюзов 192.168.25.8 и 192.168.25.9 попадает в контекст FIFA-IN дайлплана Asterisk, здесь, в зависимости от одного из пяти набранных номеров, вызов попадает на нужный экстеншен, например, 78120002916, при помощи приложения AGI вызывается внешний скрипт из директории по умолчанию /var/lib/asterisk/agi-bin. Результат работы скрипта передаётся оператору выбора case, далее, приложение Progress() указывает Asterisk что не нужно посылать SIP 200OK, что равно соединению и началу тарификации, а проиграть голосовое сообщение в режиме предответа(early media) с помощью приложения Playback, затем послать сигнал занято — Busy(10) и повесить трубку Hangup. Аудиофайлы, которые нужно проиграть загружаются в /var/lib/asterisk/sounds/ru/.
Для контроля содержимого ответа в CDR Asterisk добавим содержимое переменой ANSWER при помощи приложения Set,
Set(CDR(userfield)=${ANSWER});
Далее, в примере CDR содержимое полученного значения переменной будет продемонстрировано.
Ниже два примера скрипта написанные на bash и Python3, скрипты передают номера и возвращают в дайлплан результат.
#cat /var/lib/asterisk/agi-bin/get-res.sh

#!/bin/bash

res=`curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d"user_phone=$1&gw_phone=$2" http://wfff-loginpage:8008/ivr_auth| sed -n 's/^.*resultCode=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`

echo $res
echo -e "SET VARIABLE RES $res";
sleep 0
exit 0

Здесь я использовал консольную утилиту curl для http запроса на сервер авторизации. Кстати, последняя строчка exit 0, иначе в консоли Asterisk будут появляться ошибки результаты работы AGI-скрипта.
Ниже аналогичный скрипт на языке Python3, который я использовал в «боевой» конфигурации.


#!/usr/bin/env python3

import requests
from sys import argv
user_phone,gw_phone = argv[1:]
answer = requests.post('http://wfff-loginpage:8008/ivr_auth',headers={'Content-Type': 'application/x-www-form-urlencoded'},data={'user_phone': user_phone,'gw_phone': gw_phone})
#res='resultCode=0&resultMessage=rejected'
answer=str(answer.content)
print("SET VARIABLE RES %s" % answer[13] +"\n"+"SET VARIABLE ANSWER %s" % answer)

Здесь я использовал отличный модуль для http запросов requests. На этом настройка Asterisk закончена.

В CDR вызовы будут выглядеть так:

"","+00000637658","sw_5_0","FIFA-IN",""""" <+00000637658>","SIP/FIFA-1-000034c0","","Busy","10","2018-07-15 18:54:34",,"2018-07-15 18:54:41",7,0,"BUSY","DOCUMENTATION","1531670074.27007","b'resultCode=0&amp;amp;resultMessage=rejected'"

"","79060003159","sw_4_1","FIFA-IN",""""" <79060003159>","SIP/FIFA-2-000034c1","","Busy","10","2018-07-15 18:55:22",,"2018-07-15 18:55:31",8,0,"BUSY","DOCUMENTATION","1531670122.27010","b'resultCode=1&amp;amp;resultMessage=accepted'"

По мониторингу Asterisk использую следующие основные параметры, ниже пример конфигурации для Zabbix файл /etc/zabbix/zabbix_agentd.conf в UserParameter:

### Option: UserParameter
#Текущие вызовы
UserParameter=asterisk.core.show.calls,/usr/bin/sudo /usr/sbin/asterisk -rx 'core show calls' | grep active| awk '{print $1}'
#Текущие каналы SIP
UserParameter=asterisk.sip.show.channels,/usr/bin/sudo /usr/sbin/asterisk -rx 'sip show channels' | grep "active SIP dialog" | awk '{print $1}'
#Обработанные звонки, накопительный счётчик
UserParameter=asterisk.sip.show.calls.processed,/usr/bin/sudo /usr/sbin/asterisk -rx 'core show calls' | grep processed | awk '{print $1}'

Медиасервер Freeswitch

IP-адрес=192.168.25.32
У Freeswitch есть встроенный модуль curl.
Нам надо добавить модуль mod_curl поэтому, при компиляции снимаем комментарий с требуемых модулей в
/usr/src/freeswitch/modules.conf

languages/mod_python
applications/mod_curl

Сохраняем. Запускаем конфигурацию сбоку и инсталляцию ещё раз:

./configure
make
make install

Теперь в конфигурационных файлах Freeswtich /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml, удаляем комментарии:

<load module="mod_curl"/>
<load module="mod_python"/>

Проверим что модуль есть:

#fs_cli
$fs_cli
freeswitch@FS1.6> module_exists mod_python
true
freeswitch@FS1.6> module_exists mod_curl
true

В файле можно /freeswitch/conf/autoload_configs/switch.conf.xml можно увеличить данные параметры:

<param name="max-sessions" value="1000"/>
    <!--Most channels to create per second -->
    <param name="sessions-per-second" value="30"/>
    <!-- Default Global Log Level - value is one of debug,info,notice,warning,err,crit,alert -->
    <param name="loglevel" value="debug"/>

Внешние каналы SIP, добавим новый профиль:

#touch /freeswitch/conf/sip_profiles/fifa.xml

Добавим в файл следующие строки:

<settings>
    <param name="debug" value="0"/>
    <param name="sip-trace" value="no"/>
    <param name="sip-capture" value="no"/>
    <param name="rfc2833-pt" value="101"/>
    <param name="sip-port" value="$${external_sip_port}"/>
    <param name="dialplan" value="XML"/>
    <param name="context" value="fifa"/>
    <param name="dtmf-duration" value="2000"/>
    <param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
    <param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
    <param name="hold-music" value="$${hold_music}"/>
    <param name="rtp-timer-name" value="soft"/>
    <param name="local-network-acl" value="localnet.auto"/>
    <param name="manage-presence" value="false"/>
  <param name="rtp-ip" value="192.168.25.32"/>
    <param name="sip-ip" value="192.168.25.32"/>
  </settings>

Значение $${external_sip_port} это глобальный параметр, его значение указано в /freeswitch/conf/vars.xml, и выглядит так: external_sip_port=5080.

Запустим наш новый профиль:

freeswitch@wfff-media2> sofia profile fifa start
Reload XML [Success]
fifa started successfully

В консоли Linux, проверим, что IP и порт прослушивает Freeswitch:

root@wfff-media2:/freeswitch/conf/sip_profiles# netstat -anp | grep 5080
tcp        0      0 192.168.25.32:5080      0.0.0.0:*               LISTEN      5499/freeswitch
udp        0      0 192.168.25.32:5080      0.0.0.0:*                           5499/freeswitch

Теперь переходим к настройке дайлплана, файл /freeswitch/conf/dialplan/fifa.xml:

<include>
  <context name="fifa">
<extension name="FIFA_NUM_POOL" continue="true">
    <condition field="destination_number" expression="^(.*)$">
            <action application="curl" data="http://wfff-loginpage:8008/ivr_auth content-type 'application/x-www-form-urlencoded' post user_phone=${caller_id_number}&amp;amp;gw_phone=${destination_number:1}" inline="true"/>
            <!--action application="set" data="answer=resultCode=0&amp;amp;resultMessage=rejected"/-->
            <!--action application="set" data="respdata=${curl_response_data}"/-->
            <action application="set" data="result=${curl_response_data:11:1}" inline="true"/>
            <action application="log" data="INFO result is ${result}" inline="true"/>
    </condition>
    <condition field="destination_number" expression="^78120002915$" break="on-true">   <!-- Russian -->
        <action application="log" data="ANI NUMBER IS ${ani} "/>
        <action application="log" data="78120002915 WARNING RESULT IS ${result} "/>
        <action application="pre_answer"/>
        <action application="playback" data="${cond(${result} == 1 ? /usr/local/freeswitch/sounds/fifa/success_readyRUS1.wav : /usr/local/freeswitch/sounds/fifa/Fail_RUS1.wav)}"/>
        <action application="sleep" data="3000"/>
        <action application="hangup" data="USER_BUSY"/>
    </condition>
        <condition field="destination_number" expression="^78120002916$" break="on-true"> <!-- English -->
        <action application="log" data="RESULT IS ${result} "/>
        <action application="pre_answer"/>
        <action application="playback" data="${cond(${result} == 1 ? /usr/local/freeswitch/sounds/fifa/Success_readyEN1.wav : /usr/local/freeswitch/sounds/fifa/Fail_EN1.wav"/>
        <action application="hangup" data="USER_BUSY"/>
    </condition>
 </context>
 </include>

Затем перезагружаем дайлплан:

freeswitch@wfff-media2> reloadxml
+OK [Success]

2019-02-22 13:32:23.277861 [INFO] mod_enum.c:879 ENUM Reloaded
2019-02-22 13:32:23.277861 [INFO] switch_time.c:1423 Timezone reloaded 1750 definitions

Всё, на этом настройка закончена.

Что происходит в дайлплан?

В модуль SIP медиасервера Freeswitch (использует Sofia) приходит вызов, в соответствии с созданным sip профилем FIFA вызов направляется в контекст fifa для обработки.
Контекст fifa содержит единственный эктеншен с именем FIFA_NUM_POOL. В первое условие(condition) содержит правило

<condition field="destination_number" expression="^(.*)$">

Поэтому туда попадает любой позвонивший пользователь. Начинается первая фаза ROUTING – формирования найденного по совпавшим в условиям списка действий(actions) TODO. Значение break в первом условии (condition) отсутствует, это равно break=”on-false”, то есть
не проверять следующее условие condition, если это условие ложно, но оно всегда в нашем случае истинно. Далее, проверяются остальные условия conditions которые содержат 5 номеров, соответствующих языку, на котором воспроизводятся голосовые подсказки, в примере я показываю только два номера 78120002915 и 78120002916. Когда условие по номеру позвонившего или destination_number совпадает с набранным пользователем номером, срабатывает директива break=»on-true», что значит прервать просмотр условий (condition)и запустить те условия, которые совпали. То есть первое и второе, одно из пяти. Причём условия как бы стекируются и связаны межу собой оператором И(AND).
Список на выполнение или TODO список действии(action) составлен, начинается фаза выполнения State EXECUTE.
Запускается первое приложение curl:

<action application="curl" data="http://wfff-loginpage:8008/ivr_auth content-type 'application/x-www-form-urlencoded' post user_phone=${caller_id_number}&amp;amp;gw_phone=${destination_number:1}"/>

Мы отправляем сообщение POST в формате JSON номер звонящего и номер телефона на который позвонили, при этому удаляем первую цифру номера.
В ответ получаем ответ, наподобие

resultCode=1&amp;amp;resultMessage=accepted

Приложение curl возвращает результа в стандартную переменную curl_response_data
Так как интересующее нас значение находится в 11 символе, извлечём её при помощи конструкции

<action application="set" data="result=${curl_response_data:11:1}" inline="true"/>

и присвоим переменной result.
Здесь запускается приложение curl, которое проверяет телефонный номер и возвращает результат в переменную ${result}. Далее, выполняются действия из второго найденного условия, во-первых

<action application="pre_answer"/>

означает что мы будем проигрывать сообщение в предответном состоянии, без начала тарификации.
Следующее действие:

        <action application="playback" data="${cond(${result} == 1 ? /usr/local/freeswitch/sounds/fifa/success_readyRUS1.wav : /usr/local/freeswitch/sounds/fifa/Fail_RUS1.wav)}"/>

Тут мы воспроизводим файл success_readyRUS1.wav, если значение переменной ${result}=1 или файл Fail_RUS1.wav в противном случае.
Сследующие действия:

        <action application="sleep" data="3000"/>
        <action application="hangup" data="USER_BUSY"/>

Ждём 3000 миллисекунд и запускаем приложение «отбой» с кодом USER_BUSY или SIP 486.
Результат в CDR Freeswitch представлен ниже.
Если абонент авторизован:

"70002783772","70002783772","78120002915","fifa","2018-07-17 13:40:58","","2018-07-17 13:41:05","7","0","ORIGINATOR_CANCEL","c6337123-7a94-4ba2-96ee-17d00d2e460b","","","PCMA","PCMA","resultCode=1&amp;amp;resultMessage=accepted"

Если абоненту отказано в авторизации:

"70002254963","70002254963","78120002918","fifa","2018-07-17 17:13:23","","2018-07-17 17:13:34","11","0","USER_BUSY","854529fc-62c6-479a-8c10-4c639fa624d9","","","PCMA","PCMA","resultCode=0&amp;amp;resultMessage=rejected"

Как видно, в cdr отображается содержимое переменной ${curl_response_data}

Чтобы добавить её в CDR, нужно сделать следующее:

Открыть на редактирование файл /usr/local/freeswitch/conf/autoload_configs/cdr_csv.conf.xml, далее, смотрим какой используется темплейт для CDR:

 <param name=«default-template» value=«example»/>

Затем, в

<template name=«example»>

добавляем в конце по образцу «${curl_response_data}»
Получится:

  <template name="example">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}","${curl_response_data}"</template>

Сохраняем.

Затем делаем перезагрузку модуля из fs_cli

 freeswitch@debian8> reload mod_cdr_csv

Ниже лог примера выполнения дайлплана Freeswitch.

====Вызов пришёл в модуль Sofia SIP====

2019-02-22 17:38:40.497865 [NOTICE] switch_channel.c:1104 New Channel sofia/fifa/79500090900@192.168.25.9 [dac48249-f16f-4026-b176-d29d0719b8dc]
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:584 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_NEW (Cur 1 Tot 13675)
2019-02-22 17:38:40.497865 [DEBUG] sofia.c:9873 sofia/fifa/79500090900@192.168.25.9 receiving invite from 192.168.25.9:5060 version: 1.6.20 git 43a9feb 2018-05-07 18:56:11Z 64bit
2019-02-22 17:38:40.497865 [DEBUG] sofia.c:7084 Channel sofia/fifa/79500090900@192.168.25.9 entering state [received][100]
2019-02-22 17:38:40.497865 [DEBUG] sofia.c:7094 Remote SDP:
v=0
o=- 1060 847210 IN IP4 192.168.25.9
s=SMG SIP session
c=IN IP4 192.168.25.9
t=0 0
m=audio 25862 RTP/AVP 8 0
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=ptime:20

2019-02-22 17:38:40.497865 [DEBUG] sofia.c:7486 (sofia/fifa/79500090900@192.168.25.9) State Change CS_NEW -> CS_INIT
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:603 (sofia/fifa/79500090900@192.168.25.9) State NEW
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:584 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_INIT (Cur 1 Tot 13675)
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:627 (sofia/fifa/79500090900@192.168.25.9) State INIT
2019-02-22 17:38:40.497865 [DEBUG] mod_sofia.c:90 sofia/fifa/79500090900@192.168.25.9 SOFIA INIT
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:40 sofia/fifa/79500090900@192.168.25.9 Standard INIT
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:48 (sofia/fifa/79500090900@192.168.25.9) State Change CS_INIT -> CS_ROUTING
2019-02-22 17:38:40.497865 [DEBUG] switch_core_state_machine.c:627 (sofia/fifa/79500090900@192.168.25.9) State INIT going to sleep
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:584 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_ROUTING (Cur 1 Tot 13675)
2019-02-22 17:38:40.517818 [DEBUG] switch_channel.c:2249 (sofia/fifa/79500090900@192.168.25.9) Callstate Change DOWN -> RINGING
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:643 (sofia/fifa/79500090900@192.168.25.9) State ROUTING
2019-02-22 17:38:40.517818 [DEBUG] mod_sofia.c:143 sofia/fifa/79500090900@192.168.25.9 SOFIA ROUTING
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:236 sofia/fifa/79500090900@192.168.25.9 Standard ROUTING
2019-02-22 17:38:40.517818 [INFO] mod_dialplan_xml.c:637 Processing 79500090900 <79500090900>->78120002915 in context fifa

=== Вызов ушёл в контекст fifa =====

Dialplan: sofia/fifa/79500090900@192.168.25.9 parsing [fifa->FIFA_NUM_POOL] continue=false
Dialplan: sofia/fifa/79500090900@192.168.25.9 Regex (PASS) [FIFA_NUM_POOL] destination_number(78120002915) =~ /^(.*)$/ break=on-false

===Условие сработало, добавить действия в этом условии в TODO список, фаза 1 ===

Dialplan: sofia/fifa/79500090900@192.168.25.9 Action curl(http://wfff-loginpage:8008/ivr_auth content-type 'application/x-www-form-urlencoded' post user_phone=${caller_id_number}&amp;amp;gw_phone=${destination_number:1})
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action set(result=${curl_response_data:11:1})
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action log(INFO result is ${result})
Dialplan: sofia/fifa/79500090900@192.168.25.9 Regex (FAIL) [FIFA_NUM_POOL] ani(79500090900) =~ /^71110007780$/ break=on-true
Dialplan: sofia/fifa/79500090900@192.168.25.9 Regex (PASS) [FIFA_NUM_POOL] destination_number(78120002915) =~ /^78120002915$/ break=on-true

===Условие destination_number(78120002915)  сработало, добавить действия в этом условии в TODO список, другие условия проверяться не будут так как установлено break=on-true ===

Dialplan: sofia/fifa/79500090900@192.168.25.9 Action log(ANI NUMBER IS ${ani} )
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action log(78120002915 WARNING RESULT IS ${result} )
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action pre_answer()
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action playback(${cond(${result} == 1 ?  /usr/local/freeswitch/sounds/fifa/success_readyRUS1.wav : /usr/local/freeswitch/sounds/fifa/Fail_RUS1.wav)})
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action sleep(3000)
Dialplan: sofia/fifa/79500090900@192.168.25.9 Action hangup(USER_BUSY)
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:286 (sofia/fifa/79500090900@192.168.25.9) State Change CS_ROUTING -> CS_EXECUTE
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:643 (sofia/fifa/79500090900@192.168.25.9) State ROUTING going to sleep
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:584 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_EXECUTE (Cur 1 Tot 13675)
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:650 (sofia/fifa/79500090900@192.168.25.9) State EXECUTE
2019-02-22 17:38:40.517818 [DEBUG] mod_sofia.c:198 sofia/fifa/79500090900@192.168.25.9 SOFIA EXECUTE
2019-02-22 17:38:40.517818 [DEBUG] switch_core_state_machine.c:328 sofia/fifa/79500090900@192.168.25.9 Standard EXECUTE

====Начало запуска условии в состоянии EXECUTE, фаза 2. Выполняются действия из совпавших условий.

EXECUTE sofia/fifa/79500090900@192.168.25.9 curl(http://wfff-loginpage:8008/ivr_auth content-type 'application/x-www-form-urlencoded' post user_phone=79500090900&amp;amp;gw_phone=8120002915)
2019-02-22 17:38:40.517818 [DEBUG] mod_curl.c:182 method: post, url: http://wfff-loginpage:8008/ivr_auth, content-type: application/x-www-form-urlencoded
2019-02-22 17:38:40.517818 [DEBUG] mod_curl.c:211 Post data: user_phone=79500090900&amp;amp;gw_phone=8120002915
EXECUTE sofia/fifa/79500090900@192.168.25.9 set(result=0)

=== От curl получен результат 0 ===

2019-02-22 17:38:40.557875 [DEBUG] mod_dptools.c:1548 SET sofia/fifa/79500090900@192.168.25.9 [result]=[0]
EXECUTE sofia/fifa/79500090900@192.168.25.9 log(INFO result is 0)
2019-02-22 17:38:40.557875 [INFO] mod_dptools.c:1742 result is 0
EXECUTE sofia/fifa/79500090900@192.168.25.9 log(ANI NUMBER IS 79500090900 )
2019-02-22 17:38:40.557875 [DEBUG] mod_dptools.c:1742 NUMBER IS 79500090900
EXECUTE sofia/fifa/79500090900@192.168.25.9 log(78120002915 WARNING RESULT IS 0 )
EXECUTE sofia/fifa/79500090900@192.168.25.9 pre_answer()

=== Состояние предответа ===

2019-02-22 17:38:40.557875 [INFO] mod_dptools.c:1355 Sending early media
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMA:8:8000:20:64000:1]/[opus:116:48000:20:0:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMA:8:8000:20:64000:1]/[G722:9:8000:20:64000:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMU:0:8000:20:64000:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4504 Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMU:0:8000:20:64000:1]/[opus:116:48000:20:0:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMU:0:8000:20:64000:1]/[G722:9:8000:20:64000:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMU:0:8000:20:64000:1]/[PCMU:0:8000:20:64000:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4504 Audio Codec Compare [PCMU:0:8000:20:64000:1] ++++ is saved as a match
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4449 Audio Codec Compare [PCMU:0:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:3061 Set Codec sofia/fifa/79500090900@192.168.25.9 PCMA/8000 20 ms 160 samples 64000 bits 1 channels
2019-02-22 17:38:40.557875 [DEBUG] switch_core_codec.c:111 sofia/fifa/79500090900@192.168.25.9 Original read codec set to PCMA:8
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4738 No 2833 in SDP. Liberal DTMF mode adding 101 as telephone-event.
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:4767 sofia/fifa/79500090900@192.168.25.9 Set 2833 dtmf send payload to 101 recv payload to 101
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:6878 AUDIO RTP [sofia/fifa/79500090900@192.168.25.9] 192.168.25.32 port 16452 -> 192.168.25.9 port 25862 codec: 8 ms: 20
2019-02-22 17:38:40.557875 [DEBUG] switch_rtp.c:4137 Starting timer [soft] 160 bytes per 20ms
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:7180 sofia/fifa/79500090900@192.168.25.9 Set 2833 dtmf send payload to 101
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:7187 sofia/fifa/79500090900@192.168.25.9 Set 2833 dtmf receive payload to 101
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:7210 sofia/fifa/79500090900@192.168.25.9 Set rtp dtmf delay to 40
2019-02-22 17:38:40.557875 [NOTICE] sofia_media.c:92 Pre-Answer sofia/fifa/79500090900@192.168.25.9!
2019-02-22 17:38:40.557875 [DEBUG] switch_channel.c:3474 (sofia/fifa/79500090900@192.168.25.9) Callstate Change RINGING -> EARLY
2019-02-22 17:38:40.557875 [DEBUG] switch_core_media.c:6861 Audio params are unchanged for sofia/fifa/79500090900@192.168.25.9.
2019-02-22 17:38:40.557875 [DEBUG] mod_sofia.c:2364 Ring SDP:
v=0
o=FreeSWITCH 1550829868 1550829869 IN IP4 192.168.25.32
s=FreeSWITCH
c=IN IP4 192.168.25.32
t=0 0
m=audio 16452 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv

=== Начало проигрывания звукового файла Fail_RUS1.wav ===

EXECUTE sofia/fifa/79500090900@192.168.25.9 playback(/usr/local/freeswitch/sounds/fifa/Fail_RUS1.wav)
2019-02-22 17:38:40.557875 [DEBUG] sofia.c:7084 Channel sofia/fifa/79500090900@192.168.25.9 entering state [early][183]
2019-02-22 17:38:40.557875 [DEBUG] switch_ivr_play_say.c:1498 Codec Activated L16@8000hz 1 channels 20ms
2019-02-22 17:38:40.657867 [DEBUG] switch_rtp.c:7308 Correct audio ip/port confirmed.
2019-02-22 17:38:49.677867 [DEBUG] sofia.c:7084 Channel sofia/fifa/79500090900@192.168.25.9 entering state [terminated][487]
2019-02-22 17:38:49.677867 [NOTICE] sofia.c:8273 Hangup sofia/fifa/79500090900@192.168.25.9 [CS_EXECUTE] [ORIGINATOR_CANCEL]
2019-02-22 17:38:49.677867 [DEBUG] switch_ivr_play_say.c:1942 done playing file /usr/local/freeswitch/sounds/fifa/Fail_RUS1.wav
2019-02-22 17:38:49.677867 [DEBUG] switch_core_session.c:2815 sofia/fifa/79500090900@192.168.25.9 skip receive message [APPLICATION_EXEC_COMPLETE] (channel is hungup already)
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:650 (sofia/fifa/79500090900@192.168.25.9) State EXECUTE going to sleep
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:584 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_HANGUP (Cur 1 Tot 13675)
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:850 (sofia/fifa/79500090900@192.168.25.9) Callstate Change EARLY -> HANGUP
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:852 (sofia/fifa/79500090900@192.168.25.9) State HANGUP
2019-02-22 17:38:49.677867 [DEBUG] mod_sofia.c:438 Channel sofia/fifa/79500090900@192.168.25.9 hanging up, cause: ORIGINATOR_CANCEL
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:60 sofia/fifa/79500090900@192.168.25.9 Standard HANGUP, cause: ORIGINATOR_CANCEL
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:852 (sofia/fifa/79500090900@192.168.25.9) State HANGUP going to sleep
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:619 (sofia/fifa/79500090900@192.168.25.9) State Change CS_HANGUP -> CS_REPORTING
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:584 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_REPORTING (Cur 1 Tot 13675)
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:938 (sofia/fifa/79500090900@192.168.25.9) State REPORTING
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:174 sofia/fifa/79500090900@192.168.25.9 Standard REPORTING, cause: ORIGINATOR_CANCEL
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:938 (sofia/fifa/79500090900@192.168.25.9) State REPORTING going to sleep
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:610 (sofia/fifa/79500090900@192.168.25.9) State Change CS_REPORTING -> CS_DESTROY
2019-02-22 17:38:49.677867 [DEBUG] switch_core_session.c:1665 Session 13675 (sofia/fifa/79500090900@192.168.25.9) Locked, Waiting on external entities
2019-02-22 17:38:49.677867 [NOTICE] switch_core_session.c:1683 Session 13675 (sofia/fifa/79500090900@192.168.25.9) Ended
2019-02-22 17:38:49.677867 [NOTICE] switch_core_session.c:1687 Close Channel sofia/fifa/79500090900@192.168.25.9 [CS_DESTROY]
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:741 (sofia/fifa/79500090900@192.168.25.9) Running State Change CS_DESTROY (Cur 0 Tot 13675)
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:751 (sofia/fifa/79500090900@192.168.25.9) State DESTROY
2019-02-22 17:38:49.677867 [DEBUG] mod_sofia.c:343 sofia/fifa/79500090900@192.168.25.9 SOFIA DESTROY
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:181 sofia/fifa/79500090900@192.168.25.9 Standard DESTROY
2019-02-22 17:38:49.677867 [DEBUG] switch_core_state_machine.c:751 (sofia/fifa/79500090900@192.168.25.9) State DESTROY going to sleep

По мониторингу Freeswitch использую следующие основные параметры, ниже пример конфигурации для Zabbix файл /etc/zabbix/zabbix_agentd.conf в UserParameter :

### Option: UserParameter
####Channel count
UserParameter=fs.channels.count.current, /usr/local/freeswitch/bin/fs_cli -x "show channels count" | grep total | awk {'print $1'}
UserParameter=fs.channels.count.max.5.min, /usr/local/freeswitch/bin/fs_cli -x "status" | grep 'session(s) - peak' |  awk '{print $8}'
####CPS count
UserParameter=fs.cps.count.current, /usr/local/freeswitch/bin/fs_cli -x "status" | grep ' session(s) - peak' | awk '{print $1}'
UserParameter=fs.cps.count.max.5.min,/usr/local/freeswitch/bin/fs_cli -x "status" | grep 'session(s) per Sec out of max' | awk '{print $13}'
###Sessions count since startup
UserParameter=fs.sessions.count.since.startup,/usr/local/freeswitch/bin/fs_cli -x "status" | grep "session(s) since startup" | awk {'print $1'}

Итог

Для задачи авторизации в сети Wi-Fi по звонку отлично подойдёт любое из решений, Asterisk проще в конфигурировании, Freeswitch несколько сложнее, зато у него есть модуль curl и не нужно вызывать внешний скрипт, но скрипт написать не сложно. По производительности я не заметил разницы, наверное, потому что нагрузка была не существенная. Вот по качеству воспроизведения подсказок, по моей субъективной оценке, Freeswtich звучал лучше. По отладке и мониторингу, больше нравится Freeswitch, потому что логичнее и понятнее сообщения Freeswitch, также можно мониторить больше переменных, особенно порадовало наличие параметра Call per Second(CPS). В целом, по логической организации Freeswitch тоже больше нравится, но xml конфигурация Freeswtich несколько сложнее для восприятия, чем язык ael дайлплана Astersik, хотя со временем чтение и написание xml не вызывает никаких сложностей.

Автор: Игнат Кудрявцев

Tags: ,

Комментарии:

Оставить комментарий

Напишите Ваш комментарий ниже. Также Вы можете подписаться на комментарии к материалу через RSS

Вы можете использовать следующие теги:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

Мы поддерживаем Gravatar.

Контроль спама: *