Для начала, что такое диалплан. Диалплан — это схема маршрутизации вызовов (звонков). В диалплане мы проверяем некоторые параметры вызова (например, номер вызывающего и вызываемого абонента) и на основании значения этих параметров указываем, куда перенаправить этот вызов дальше — на локальный номер, на шлюз оператора, в голосовую почту и т.д.
Для Freeswitch дефолтным диалпланом является XML dialplan. XML dialplan подключается к главному конфигурационному файлу freeswitch.xml с помощью include:
<section name="dialplan" description="Regex/XML Dialplan">
<X-PRE-PROCESS cmd="include" data="dialplan/*.xml"/>
</section>
Диалплан может быть поделен на контексты (context) для разделения правил обработки и маршрутизации между разными группами пользователей. Пользователь с одним контекстом не может воспользоваться диалпланом другого контекста. Но существует возможность перенаправления вызовов между контекстами с помощью приложений диалплана (application).
Когда поступает входящий вызов, он поступает не из-неоткуда, он поступает от какого-либо зарегистрированного на Freeswitch абонента (будь то локальный абонент, или gateway оператора, или вызов может быть сгенерирован самим Freeswitch) и попадает сперва в обработку модуля mod_sofia. В Sofia вычисляются значения канальных переменных — channel variables — на основании значений в sip-заголовках входящего вызова, согласованных параметров вызова между вызывающим абонентом и Freeswitch, параметров, выставленных вручную в directory. Затем уже Freeswitch, используя вычисленные канальные переменные, парсит диалплан в поисках подходящего направления для данного вызова.
Диалплан работает по принципу «условие-действие»; «условие» задается в виде регулярного выражения — используется синтаксис Perl Regular Expression; «действие» — это одно или несколько приложений Freeswitch, также в качестве «действия» можно подключать свои внешние скрипты.
XML dialplan состоит из таких структурных единиц, как:
- context (контекст),
- extension («направление»),
- condition (условие),
- action (действие).
context состоит из множества extension, которые с помощью condition определяют action.
<context name="default">
<extension name="local-extension">
<condition field="destination_number" expression="^(100)$">
<action application="bridge" data="user/100"/>
</condition>
</extension>
</context>
context
— логическое разделения групп правил маршрутизации вызовов.
Когда вы создаете пользователя в directory, в переменной «user_context» вы указываете контекст, который пользователь может использовать для совершения вызовов — тем самым вы определяете набор доступных extension (направлений) для данного пользователя или группы пользователей, или всего домена. Если вы этого не сделаете, будет применяться контекст, указанный в переменной «context» sip-профиля.
Из выше сказанного и знаний про работу sip-профиля можно сделать следующие выводы: в sip-профиле может быть сколько угодно контекстов; в домене может быть сколько угодно контекстов; можно отдельного пользователя в домене завернуть в его отдельный контекст и чисто для этого пользователя написать диалплан; можно один контекст использовать для нескольких доменов.
context имеет обязательный параметр — это «name» — он должен быть уникальным. Для значения параметра name есть зарезервированное слово any — которое означает «любой контекст».
extension
— это отдельное направления для вызова — упрощенно — отдельная пара «условие-действие».
Также имеет обязательный параметр «name«, значение этого параметра может быть неуникальным; используется для описания extension — часто в name кратко описывают, что делает данный extension — это облегчает восприятие диалплана при просмотре его «глазками» без необходимости лезть внутрь самого екстеншена. При принятии решения о маршрутизации вызова Freeswitch парсит extension’ы и как только находит подходящий, на нем и останавливается, не досматривая остальные extension’ы до конца.
condition
— условие для выбора.
Здесь задаем, какую переменную проверяем, и под какое условие должно попасть значение этой переменной, чтобы применился данный extension. Можно сохранить значение всей переменной или непрерывную часть значения, для того, чтобы ее дальше можно было использовать в action. Для этого регулярное выражение или часть регулярного выражения заключаем в круглые скобки ( ). То, что окажется в пределах круглых скобок, сохранится в специальных переменных — $1, $2 … $9. Поскольку condition’ов может быт несколько, то и скобок в регулярных выражениях может быть несколько. Значение, попавшее в первые скобки, заносится в переменную $1, во вторые — $2 и т.д.
На примере:
<condition field="destination_number" expression="^\d\d(\d\d)$">
<action application="bridge" data="user/$1@example.com"/>
</condition>
здесь мы проверяем номер вызываемого абонента (destination_number) — он должен состоять из любых 4-х цифр. Если условие выполняется — то последние 2 цифры заносятся в переменную $1. Например, если destination_number=3589, то переменная $1=89.
Если после переменной $N нужно записать еще какую-то цифру, число, то используем фигурные скобки — ${N}
<condition field="destination_number" expression="^\d\d(\d\d)$">
<action application="bridge" data="user/${1}50@example.com"/>
</condition>
$1, $2 … $9 работают только в пределах того extension, где они были вычислены.
Переменных $10, $11, $12 и т.д. здесь не бывает. Если нужно переменных больше, чем 9, есть специальные приемы, но о них как-нибудь потом.
action
действие, которое мы выполняем, если мы попали под условие condition. Здесь мы указываем действие — это может быть направление вызова, установление каких-либо параметров, проигрывание музыки и т.д. Действие — это запуск определенного приложения (application).
В противовес action, есть еще anti-action — это действие, которое выполняется, когда результат проверки условий — false:
<condition wday="2-6" time-of-day="09:00-18:00">
<action application="transfer" data="1000 XML default"/>
<anti-action application="transfer" data="2000 XML default"/>
</condition>
Написание тегов
Хочу обратить внимание на соблюдение порядка открывающих/закрывающих тегов.
<condition … > — открывающий тег
</condition> — закрывающий тег
<action … /> — не имеет отдельного закрывающего тега, поэтому в конце не забудьте про слеш
Если condition’ов несколько, то все, кроме последнего закрываем с помощью />, а последний condition закрываем </condition>
<condition … />
<condition … />
<condition … >
<action … />
</condition>