Пользователи за АТС
Введение
Система работает как софтсвич в центре, а на переферии находятся подразделения. Подразделения к системе подключены через атс-ки. АТС-ки регистрируются на системе как на провайдере. Задача - звонить на АТСку не как на телефон, а пробрасывая набранный номер.
То есть, например, в системе есть учетки 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, которой он соответствует.