Сравниваем конфигурации Freeswitch и Asterisk для одной задачи
Для чемпионата мира в России, который прошёл в 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 можно найти по данной ссылке.
Оба шлюза подключены к городской АТС, где также создана группа терминации с алгоритмом работы по очереди. Такая схема даёт равномерное распределение нагрузки по шлюзам и медиасерверам.
Когда медиасервер получает вызов, он делает запрос по 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;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;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;gw_phone=${destination_number:1}" inline="true"/> <!--action application="set" data="answer=resultCode=0&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;gw_phone=${destination_number:1}"/>
Мы отправляем сообщение POST в формате JSON номер звонящего и номер телефона на который позвонили, при этому удаляем первую цифру номера.
В ответ получаем ответ, наподобие
resultCode=1&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;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;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;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;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;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: Asterisk, Freeswitch