воскресенье, 7 февраля 2016 г.
Использование поля Diversion в SIP пакете и возможные решения проблемы недозвона при двойной переадресации в Asterisk.
Справка о использовании поля Diversion, а так же описание переадресации в SIP здесь: https://tools.ietf.org/html/rfc5806
При двойной переадресации вызова в Asterisk могут быть проблемы недозвона. Например, имеем схему:
Запрос INVITE, поступающий на Asterisk будет такой:
INVITE sip:2057004@10.200.104.12:5172;user=phone SIP/2.0
Accept: application/sdp;q=0.3
Accept: application/ISUP;q=0.2
Accept: multipart/mixed;q=0.1
Allow: INVITE,ACK,CANCEL,BYE,INFO,PRACK,UPDATE,OPTIONS,REGISTER,REFER,SUBSCRIBE,MESSAGE,PUBLISH
Call-ID: 41a5c682bgw882nql@10.200.101.11
Contact: "3303030" <sip:3303030@10.200.101.11:5060;user=phone>
CSeq: 298 INVITE
Expires: 3600
From: "3303030" <sip:3303030@10.200.101.11:5060;user=phone;cpc=ordinary>;tag=t8uu0piu60
To: "205704" <sip:2057004@10.200.104.12:5172;user=phone>
Organization: IskraTel
User-Agent: SI3000
Via: SIP/2.0/UDP 10.200.101.11:5060;branch=z9hG4bK-8uhf0-9alb1
Max-Forwards: 69
Subject: Call from CS6111
Diversion:"910123000"<sip:9101230000@10.200.101.11:5060>;reason=unconditional;privacy=full;counter=1
Content-Length: 233
Content-Type: application/sdp
Content-Disposition: session;handling=required
На Asterisk поступает уже переадресованный вызов с мобильного телефона. Вызов приходит с полем Diversion, в котором указывается номер телефона, на котором установлена переадресация. На Asterisk в extension.conf установлена переадресация на другой мобильный телефон.
В этой схеме можем наблюдать проблемы недозвона.
Проблема возникает из-за того, что некоторые операторы неадекватно реагируют на поле Diversion и могут отбросить вызов, если не смогут его тарифицировать.
Можно решить проблему глобально, выключив поддержку заголовка SIP Diversion глобально в sip.conf. Для этого в глобальных настройках sip.conf необходимо прописать:
send_diversion=no (по умолчанию «yes»).
Обычно Asterisk отправляет Diversion хидеры с определенным SIP invites для ретрансляции данных о переадресованных звонках. Если выключено, Asterisk не будет отсылать Diversion хидеры, Отсылка будет только если их добавят вручную.
Таким образом, установив в sip.conf
send_diversion=no
и следующие правила переадресации в extensiom.conf
exten => 2057004,1,Set(CALLERID(all)="2057004" <2057004>)
exten => 2057004,n,Dial(${OUTTRUNKSI}/89276132605,120,r)
exten => 2057004,n,Hangup()
будем иметь нормально установленный вызов:
Выходящий с Asterisk запрос INVITE не будет иметь поле Diversion:
INVITE sip:89276132605@10.200.101.11 SIP/2.0.
Via: SIP/2.0/UDP 10.200.104.12:5172;branch=z9hG4bK50851d21.
Max-Forwards: 70.
From: "2057004" <sip:2057004@10.200.104.12:5172>;tag=as07f597ec.
To: <sip:89276132605@10.200.101.11>.
Contact: <sip:2057004@10.200.104.12:5172>.
Call-ID: 26f878371ab6f22b7f68b67923197933@10.200.104.12:5172.
CSeq: 102 INVITE.
User-Agent: Asterisk PBX 13.1-cert2.
Date: Sun, 31 Jan 2016 15:01:25 GMT.
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE.
Supported: replaces, timer.
Content-Type: application/sdp.
Content-Length: 271.
Решить проблему исключения заголовка Diversion из исходящих INVITE запросов можно и локально для одного абонента, выключив глобальную настройку send_diversion, то есть установив send_diversion=yes.
При этом переадресацию в extension.conf нужно записывать вот так:
exten => 2057004,1,Set(CALLERID(all)="2057004" <2057004>)
exten => 2057004,n,Set(CALLERID(rdnis)=)
exten => 2057004,n,Dial(${OUTTRUNKSI}/89276132605,120,r)
exten => 2057004,n,Hangup()
При необходимости можно добавить второе поле Diversion в SIP пакет INVITE. Это делается так:
exten => 2057004,1,Set(CALLERID(all)="2057004" <2057004>)
exten => 2057004,n,SIPAddHeader(Diversion: <sip:2057004@10.200.104.12>\;user=phone\;privacy=off\;reason=unconditional)
exten => 2057004,n,Dial(${OUTTRUNKSI}/89276132605,120,r)
exten => 2057004,n,Hangup()
Здесь:
privacy=off -пераметр указывает удаленной стороне не верить полю Remote-Party-ID
reason=unconditional - причина перевода (reason) - безусловная переадресация (unconditional)
Пакет INVITE, ходящий с Asterisk будет такой:
INVITE sip:89276132605@10.200.101.11 SIP/2.0.
Via: SIP/2.0/UDP 10.200.104.12:5172;branch=z9hG4bK36d97725.
Max-Forwards: 70.
From: "2057004" <sip:2059590@10.200.104.12:5172>;tag=as540b20bf.
To: <sip:89276132605@10.200.101.11>.
Contact: <sip:2057004@10.200.104.12:5172>.
Call-ID: 3471e7a82c066a3b34ed1aee4a4bd18c@10.200.104.12:5172.
CSeq: 102 INVITE.
User-Agent: Asterisk PBX 13.1-cert2.
Date: Sun, 31 Jan 2016 15:13:33 GMT.
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE.
Supported: replaces, timer.
Diversion: <sip:2057004@10.200.104.12>;user=phone;privacy=off;reason=unconditional.
Diversion: "9101230000" <sip:9101230000@10.200.104.12>;reason=unconditional.
Content-Type: application/sdp.
Content-Length: 270.
Предварительная настройка ASTERISK 13, которая пригодиться всегда.
1 Делаем резервные копии базовых конфигурационных файлов
# cp /etc/asterisk/sip.conf /etc/asterisk/sip.conf.sample
# cp /etc/asterisk/extensions.conf /etc/asterisk/extensions.conf.sample
2 Настройки RTP в Asterisk:
В файле /etc/asterisk/rtp.conf в секции [general]
разрешаем хождение RTP по портам от 8000 до 20000
# nano /etc/asterisk/rtp.conf
[general]
rtpstart=8000
rtpend=20000
Рестартуем asterisk
# systemctl restart asterisk.service
3 Отключение сбора CDR в CSV файл.
CSV файл обычно располагается здесь: /var/log/asterisk/cdr-csv/Master.csv
Что бы посмотреть, что данный CDR файл используется для записи информации о вызове, выполняем команду:
# tail -f /var/log/asterisk/cdr-csv/Master.csv
и совершаем вызов через asterisk. В консоли мы должны увидеть новую CDR запись.
Для отключения записи логов CDR в файл Master.csv
- закомментировать секцию [csv] в файле /etc/asterisk/cdr.conf
# nano /etc/asterisk/cdr.conf
Должно получиться:
;[csv]
;usegmtime=yes ; log date/time in GMT. Default is "no"
;loguniqueid=yes ; log uniqueid. Default is "no"
;loguserfield=yes ; log user field. Default is "no"
;accountlogs=yes ; create separate log file for each account code. Default is "yes"
- Убрать из загрузки модуль модуль cdr_csv.so в /etc/asterisk/modules.conf:
# nano /etc/asterisk/modules.conf
Добавляем к конец строчку:
noload =>cdr_csv.so
- Рестартуем сервис Asterisk
# systemctl restart asterisk.service
4 Настаиваем сбор CDR файлов сервера asterisk в базу данных MySQL
Коннектимся к MySQL
# mysql -uroot -p
Создаем базу данных
> CREATE DATABASE asterisk;
Подключаемся к базе данных
> USE asterisk;
Создаем таблицу
> CREATE TABLE IF NOT EXISTS `cdr` (
`calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`clid` varchar(80) NOT NULL DEFAULT '',
`src` varchar(80) NOT NULL DEFAULT '',
`dst` varchar(80) NOT NULL DEFAULT '',
`dcontext` varchar(80) NOT NULL DEFAULT '',
`channel` varchar(80) NOT NULL DEFAULT '',
`dstchannel` varchar(80) NOT NULL DEFAULT '',
`lastapp` varchar(80) NOT NULL DEFAULT '',
`lastdata` varchar(80) NOT NULL DEFAULT '',
`duration` int(11) NOT NULL DEFAULT '0',
`billsec` int(11) NOT NULL DEFAULT '0',
`disposition` varchar(45) NOT NULL DEFAULT '',
`amaflags` int(11) NOT NULL DEFAULT '0',
`accountcode` varchar(20) NOT NULL DEFAULT '',
`uniqueid` varchar(32) NOT NULL DEFAULT '',
`remote_signal_ip` varchar(17) CHARACTER SET utf8 NOT NULL,
`userfield` varchar(255) NOT NULL DEFAULT '',
`did` varchar(50) NOT NULL DEFAULT '',
`recordingfile` varchar(255) NOT NULL DEFAULT '',
`cnum` varchar(40) NOT NULL DEFAULT '',
`cnam` varchar(40) NOT NULL DEFAULT '',
`outbound_cnum` varchar(40) NOT NULL DEFAULT '',
`outbound_cnam` varchar(40) NOT NULL DEFAULT '',
`dst_cnam` varchar(40) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Создаем индексы для этой таблицы:
> ALTER TABLE `cdr`
ADD KEY `calldate` (`calldate`),
ADD KEY `dst` (`dst`),
ADD KEY `accountcode` (`accountcode`),
ADD KEY `uniqueid` (`uniqueid`),
ADD KEY `did` (`did`);
Создаем пользователя asterisk с паролем passwd123
> grant all on asterisk.cdr to asterisk@'localhost' identified by 'passwd123';
Выходим из MySQL.
Сбор CDR в базу MySQL нужно выполнять через сервис ODBC.
Выполняем установку сервиса ODBC, если того еще не произошло раньше:
# yum install unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel mysql-connector-odbc
Редактируем файл драйверов сервиса ODBC /etc/odbcinst.ini
# nano /etc/odbcinst.ini
В файле не закомментированным должна быть только секция [MySQL]
[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib64/libmyodbc5.so
Setup = /usr/lib64/libodbcmyS.so
FileUsage = 1
Проверим видит ли ODBC MySQL драйвер
# odbcinst -q -d
[MySQL]
Создаем файл учетных данных ODBC /etc/odbc.ini
# nano /etc/odbc.ini
Выписываем туда следующее содержимое:
[MySQL-asteriskcdrdb]
Description=MySQL connection to 'asterisk' database
Driver=MySQL
Server=localhost
Database=asterisk
Port=3306
Socket=/var/lib/mysql/mysql.sock
UserName=asterisk
Password=passwd123
Здесь:
MySQL-asteriskcdrdb – наименование соединения с сервером MySQL
UserName – имя пользователя asterisk
Password – пароль пользователя asterisk
Правим конфигурационные файлы Asdterisk
Проверяем файл /etc/asterisk/cdr.conf
# nano /etc/asterisk/cdr.conf
В файле должен быть раскомментирован в секции [general] главный параметр enable
[general]
enable=yes
Вносим изменения в файл настройки сервиса ODBC
# nano /etc/asterisk/res_odbc.conf
Вписываем в конец файла:
[asteriskcdrdb]
enabled=>yes
dsn=>MySQL-asteriskcdrdb
pooling=>no
limit=>5
pre-connect=>yes
username=>asterisk
password=>passwd123
Связываем настройку ODBC Asterisk с задачей сбора CDR.
Редактируем файл /etc/asterisk/cdr_odbc.conf
# nano /etc/asterisk/cdr_odbc.conf
Вписываем в конец файла:
[asteriskcdrdb]
connection=asteriskcdrdb
loguniqueid=yes
table=cdr
alias start => calldate
Для того, что бы в базу данных MySQL в поле remote_signal_ip складывались ip адреса вызывающих абонентов, в диал-план в файле /etc/asterisk/extensions.conf в план набора надо написать вот эту строчку в тот контекст, при совершении вызова через который котором нужно сохранять IP адрес:
Set(CDR(remote_signal_ip)=${CHANNEL(recvip)});
Рестартуем Asterisk:
# systemctl restart asterisk.service
Теперь база данных должна пополняться вызовами, проходящими через asterisk.
Проверка работы ODBC:
asterisk2*CLI> odbc show
ODBC DSN Settings
-----------------
Name: asteriskcdrdb
DSN: MySQL-asteriskcdrdb
Last connection attempt: 1970-01-01 03:00:00
Pooled: No
Connected: Yes
5. Настройка сбора логов CEL(Channel Event Logging) в базу данных MySQL
Коннектимся к MySQL
# mysql -uroot -p
Подключаемся к базе данных asterisk
> USE asterisk;
Создаем таблицу cel
> CREATE TABLE IF NOT EXISTS `cel` (
`id` int(11) NOT NULL auto_increment,
`eventtype` varchar(30) NOT NULL,
`eventtime` datetime NOT NULL,
`cid_name` varchar(80) NOT NULL,
`cid_num` varchar(80) NOT NULL,
`cid_ani` varchar(80) NOT NULL,
`cid_rdnis` varchar(80) NOT NULL,
`cid_dnid` varchar(80) NOT NULL,
`exten` varchar(80) NOT NULL,
`context` varchar(80) NOT NULL,
`channame` varchar(80) NOT NULL,
`src` varchar(80) NOT NULL,
`dst` varchar(80) NOT NULL,
`channel` varchar(80) NOT NULL,
`dstchannel` varchar(80) NOT NULL,
`appname` varchar(80) NOT NULL,
`appdata` varchar(80) NOT NULL,
`amaflags` int(11) NOT NULL,
`accountcode` varchar(20) NOT NULL,
`uniqueid` varchar(32) NOT NULL,
`linkedid` varchar(32) NOT NULL,
`peer` varchar(80) NOT NULL,
`userdeftype` varchar(255) NOT NULL,
`eventextra` varchar(255) NOT NULL,
`userfield` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `uniqueid_index` (`uniqueid`),
KEY `eventtime_index` (`eventtime`),
KEY `linkedid_index` (`linkedid`)
);
Даем пользователю asterisk возможность работы с таблицей cel
> grant all on asterisk.cel to asterisk@'localhost' identified by 'passwd123';
Выходим из MySQL.
Включаем генерацию CEL в asterisk:
# nano /etc/asterisk/cel.conf
В разделе [general] должно быть прописано
[general]
enable=yes
apps=all
events=ALL
dateformat = %F %T
Затем указываем asterisk, куда заносить сгенерированные события CEL
# nano /etc/asterisk/cel_odbc.conf
В конец файла дописываем:
[cel]
connection=asteriskcdrdb
loguniqueid=yes
table=cel
Здесь cel – название таблицы в MySQL, asteriskcdrdb – название соединения ODBC из файла /etc/asterisk/res_odbc.conf
Перезагружаем сервис asterisk:
# systemctl restart asterisk.service
Проверка включения CEL в asterisk
# asterisk -rx "cel show status"
CEL Logging: Enabled
CEL Tracking Event: ALL
CEL Tracking Event: CHAN_START
CEL Tracking Event: CHAN_END
CEL Tracking Event: HANGUP
CEL Tracking Event: ANSWER
CEL Tracking Event: APP_START
CEL Tracking Event: APP_END
CEL Tracking Event: BRIDGE_ENTER
CEL Tracking Event: BRIDGE_EXIT
CEL Tracking Event: PARK_START
CEL Tracking Event: PARK_END
CEL Tracking Event: BLINDTRANSFER
CEL Tracking Event: ATTENDEDTRANSFER
CEL Tracking Event: USER_DEFINED
CEL Tracking Event: LINKEDID_END
CEL Tracking Event: PICKUP
CEL Tracking Event: FORWARD
CEL Tracking Event: LOCAL_OPTIMIZE
CEL Tracking Application: all
CEL Event Subscriber: ODBC CEL backend
CEL Event Subscriber: CEL Custom CSV Logging
6 Настройка обработчика джиттера в Asterisk.
Для того что бы включить компенсацию джиттера на сервере Asterisk в файл sip.conf в секцию [general] вписываем строки:
jbenable = yes
jbforce = yes
jbmaxsize = 400
jbresyncthreshold = 1000
jbimpl = fixed
Затем из консоли Asterisk выполняем
> sip reload
Подписаться на:
Сообщения (Atom)


