Пользователи за АТС
Введение
Система работает как софтсвич в центре, а на переферии находятся подразделения. Подразделения к системе подключены через атс-ки. АТС-ки регистрируются на системе как на провайдере. Задача - звонить на АТСку не как на телефон, а пробрасывая набранный номер.
То есть, например, в системе есть учетки dep1
(номер 7777
), dep2
(номер 8888
).
Звонит 11
из под dep1
. набирает 888815
, необходимо этот звонок направить в учетку dep2
, передав ему номер 15
в request-uri.
При этом From номер должен быть 777711
, так чтобы обратный вызов был возможен.
А DisplayName должен ходить насквозь, поскольку это не юзер.
Кейс решался в рамках задач #86, #189 в 2017 году.
Особенности
На атску может позвонить и любой другой абонент, в этом случае его обратный номер рассчитывается стандартно. И сама АТСка может позвонить любому другому существующему абоненту системы. То есть не обязательно из АТС в другую АТС. Таким образом разделяется реализация маршрутизации (выбора учетки и номера-назначения), и представления (построения from отправляемого INVITE-запроса).
Решение задачи маршрутизации
Вводится тип action = internalpbx
для vectorrule.
После модификации правила ролью b2b производится поиск учетной записи по принципу поиска featurecode – по максимальному совпадению префиксов (используется longmatch).
Остаток номера считается внутренним номером.
B2BUA фактически организует обычный внутренний звонок, пользуясь правилами подмены, там requesturi уже исправлен в ходе поиска и обработки правил маршрутизации.
Решение задачи представления
Подстановка From при звонке с АТС. В этом случае action
=internalpbx
для vectorrule не используется.
Признаком звонка с внутренней АТС считается отличие username в заголовке From входящего INVITE-запроса от реальной учетной записи, зарегистрированной в системе.
Реализуется в модуле r_sip_representative. Однако b2bua_router_utils используют альтернативную точку входа в representative, передавая Request. Это нужно чтобы найти реальную учетную запись sipuser. Стандартный интерфейсный метод не дает информации о прочих полях запроса, поэтому для B2BUA делается специальный метод. В нем идет сравнение username из заголовка AUTH и номера(username) из заголовка FROM.
Если заголовок AUTH не обнаружен, то это означает, что во FROM всё хорошо, система пропустила запрос, посчитав его авторизованным, и, значит, FROM.username совпадает с AUTH.username. Представление действует как обычно.
Если AUTH.username = FROM.username, то представление действует как обычно.
Если же AUTH.username отличается от FROM.username, то реальная учетка, от имени которой идет звонок, ищется исходя из AUTH.username (взамен FROM.username), вычисляется её номер и уходит в любом случае на поиск представления, даже если звонок из того же домена.
В поиск представления в доменный центр отправляется from-номер = SipUserNum + FromNum. То есть в примере выше – 888811
.
Правила представлений могут модифицировать по своему усмотрению этот номер. А если не обнаружены или не изменили, то он в таком виде подставляется во FROM отправляемого инвайта.
Значение displayname при этом (если From.username не обнаруживает учетки) пробрасывается насквозь.
Модификация DisplayName
При обслуживании звонка с устройства, зарегистрированное под учетной записью sipuser, значение ее поля name
подставляется в качестве displayname в поле From отправляемого запроса получателю.
Поле name поддерживает указание модификаторов.
-
{D}
– подставить исходный DisplayName из входящего запроса. -
{d}
– то же в lowercase. -
{U}
– подставить исходный UserName из входящего запроса. -
{u}
– то же в lowercase. -
{N}
и{n}
- подставить сформированный полный номер инициатора запроса (склеенные номера sipuser и extension). -
{A}
- подставлять displayname из учетной записи контакта адресной книги, найденного по полному номеру инициатора с extension. Если контакт не найден, то подставляется пустота. Реализовано по задаче #366. -
{a}
- то же в lowercase. -
{E}
– подставить пустоту. -
любой другой символ захватывается в результат в соответствующую ему позицию.
Например, значение может указано таким: "Peter - {D} - {N}"
, соответственно вместо модификаторов подставятся указанные выше значения из контекста текущего звонка.
Модификаторы поля displayname применяются при пробросе INVITE-запроса на второе плечо, при пробросе ответа на инициатора, а также при обслуживании re-INVITE.
Подмена значений from/extension
Нижестоящая АТС (Б) подключена по описанной выше схеме к учетной записи с номером 1234567
, при этом ее нужно вызывать как 1234567X
, то есть добавляя к номеру учетки набранный номер. Однако, сама АТС шлет звонки от 1234567X
.
При применении в чистом виде вышеописанной модели склейки номера и extension, АТС будет вызываться по номеру X
, а от нее приходящие звонки будут поступать на анализ в систему с номером 12345671234567X
.
В реализацию поступила концепция, когда сохраняется принцип "Номер учетки" + "номер extension", однако extension подвергается модификации. В sipuser вставляются поля
-
opts.modextin
, применяемое при входящем звонке с учетки в любом случае; -
opts.modextout
, применяемое к вычисленному extension при звонке internalpbx.
По умолчанию modextin
содержит пустую строку, так что мимо модификатора идет отказ от использования extension.
А modextout
по умолчанию содержит "*"
, то есть звонок уходит на вычисленный extension по остатку после long hunting.
Если же в modextin
указано нечто, то оно применяется к тому полю, которое отличается от учетной записи (может быть From username или Contact username, включая пустое значение), либо к From username, если они оба совпадают.
В модификаторе допускается использование X/X
, *
, {U}
– логин sipuser, {N}
– номер sipuser, {F}
– from username, {C}
– contact username, regex-последовательностей.
Итого для modextin
(входящие звонки с учетки в систему):
-
Чтобы входящий работал без extension как обычный sipuser телефон, не нужно указывать
modextin
, или указывать пустым (""
). From подставится номером учетной записи. -
Чтобы работать по прежней схеме (доклейка extension к username) – нужно указывать modextin =
"*"
. Однако есть два отличия от прежней схемы: (а) не будет проверки на числовое значение расширения, (б) если contact username и from username совпадают с username учетки, то на выходе получится From = конкатенации sipuser phonenumber и значения из From username. Итого From подставится склейкой номера учетной записи и преимущественно отличающегося от sipuser логина значения из From или Contact. Если не отличаются, то к номеру учетной записи добавится From из текущего запроса. Такое поведение в частности позволит нормально обслуживать extension номера, совпадающие с логином самой учетки системы «Era». -
Чтобы отработать схему c нижестоящей АТС (Б), необходимо в качестве
modextin
указать"/XXXXXXX/X"
. При этом поскольку From username (12345678
) фактически отличается от учетки (1234567
), то взяв его за основу и вырезав первые семь символов, после склейки с номером учетки sipuser получится желанная комбинация12345678
. -
Если про подключаемое устройство (АТС) известно, где именно оно размещает информацию об extension номере, то ее можно указать в
modextin
явно, например{C}
– к номеру учетки sipuser доклеится значение username из заголовка Contact INVITE-запроса.
Доступны и последовательности регулярок для модификации преимущественно отличающего значения. Даже если это значение пустое (в частности в заголовке Contact username пусто), то серией применяемых regex replace можно обработать эту ситуацию. А если не пустое и совпадает с номером учетки, то это тоже легко описывается регулярным выражением. Первая обрабатывает пустоту, вторая обрабатывает номер.
Итого для modextout
(исходящие с учетки):
-
Чтобы
internalpbx
вызывать на само имя sipuser и банить extension, нужно вmodextout
указать пустоту. Но тогда зачем internalpbx? Лучше использовать классический internal. Этот режим оставлен для общности модификаторов, но результат модификации обрабатывается особо. -
Чтобы пробросить вычисленный extension после long hunting - нужно оставить дефолт (установить) – "*". То есть пробросит
123
, если учетка с номером13
и набрано13123
. -
Чтобы решить проблему вызовов нижестоящей АТС (Б) – при звонке на
12345678
(учетка1234567
, вычисленный extension8
), нужно в качествеmodextout
указать1234567X
или567X
. Возможна последовательность регулярок. -
Если представить проблему, обратную описанной нижестоящей АТС (Б), (учетка
1234
, набирается12345678
, а он ждет8
), то/XXX/X
. То есть от вычисленного5678
вырежет8
.
При этом всем к каждому URI после разрешения в номерном плане и регистраре применится свой модификатор в соответствии с той учеткой sipuser, которой он соответствует.