В протоколе SIP достаточно часто требуется изменять поля для совместимости и решения каких-то частных задач при стыке между телефонными станциями. Это может быть, как удаление простого поля SIP, так и перенос значения из одного поля SIP в другое, либо какая-то более сложная манипуляция.
Как это можно сделать на оборудование AudioCodes SBC (Причем абсолютно на любом SBC, даже на самое младшей модели). Перед тем как начать описывать, как делается преобразование, сначала разберемся с терминологией.
В качестве примера возьмем сообщение INVITE:
INVITE sip:84951234567@10.11.12.13:5060;transport=udp SIP/2.0
Via: SIP/2.0/UDP 10.11.12.13:5060;branch=z9hG4bK-2342-1C21439
To: <sip: 84951234567@sip.sp.com;user=phone>
From: «Ivanov» <sip:4957654321@sip.sp.com;user=phone>;tag=26814-XM-09a664f9-77e583465
Allow: UPDATE,REFER,INFO
Call-ID: 26814-TO-09a664f8-0a52daf11@sip.sp.com
Contact: <sip:13.12.11.10:5060>
Content-Type: application/sdp
CSeq: 157771616 INVITE
History-Info: <sip:4952345678@20.21.22.23?reason=Forward>
Max-Forwards: 29
User-Agent: GW_SIP
Content-Length: 258
v=0
o=cp10 139660536057 139660536057 IN IP4 13.12.11.10
s=SIP Call
c=IN IP4 13.12.11.10
t=0 0
m=audio 31854 RTP/AVP 8 0 18
b=AS:80
a=rtpmap:8 PCMA/8000/1
a=rtpmap:0 PCMU/8000/1
a=rtpmap:18 G729/8000/1
a=fmtp:18
annexb=no
a=ptime:20
a=sendrecv
Для примера возьмём поле From:
From: «Ivanov» <sip:4957654321@sip.sp.com;user=phone>;tag=26814-XM-09a664f9-77e583465
Тут:
From – Заголовок
“Ivanov” – параметр заголовка display name
sip:4957654321@sip.sp.com – SIP URL, где
4957654321 – user часть SIP URL
Sip.sp.com – url часть SIP URL
Tag: параметр заголовка
AudioCodes знает достаточно много полей и может разобрать их на параметры и SIP URL. Но, понятое дело, не все, так как согласно стандарту SIP, возможно добавить любой заголовок, который нигде и никак не описан. В данном случае, для разбора данного заголовка может помочь только использование регулярных выражений. Более подробно описание того, какие заголовки знает оборудование AudioCodes, а какие не знает, описано в документации: «SIP Message Manipulations Quick Reference Guide». Ссылку тут не публикую, так как ссылка на наш сайт требует определенного уровня доступа, а выкладывать в публичный доступ не буду, так как в любой момент времени эта ссылка может прекратить жить. Если вдруг кому требуется данная документация, то пишите, обязательно поделюсь.
При создании правила манипуляции есть следующие параметры правила:
Manipulation index – номер правила. Правила обрабатываются последовательно.
Manipulation Set ID – набор правил, которые вы применяете для того или иного направления.
Message Type – типа сообщения, над которым вы планируете проводить манипуляции. Это может быть просто invite, либо ответ на invite – invite.response.200, либо ответ 2xx на register = register.response.2xx. И так далее по аналогии. Отдельно можно выделить сообщение reINVIE – reinvite.request
Condition – то, при каком условии выполняется данное правило, а при каком не выполняется. Тут можно привести простой пример header.from.url.user == ‘4957654321’. Это значит, что User часть SIP URL поля From равна 4957654321. Можно так же использовать знаки ==, !=, >=, <=, >, <, contains, !contains, exists, !exists, suffix, prefix, len>, len<, len==, regex. Все знаки можно перечислять через or или and, кроме Regex.
Action Subject – тот заголовок, который вы планируете изменить (Либо параметр заголовка). Например: header.history-info
Action value – то, что вы панируете сделать Add/Remove/Modify/Add Prefix/Add Sufix/Remove Suffix/Remove Prefix.
Action Subject – то, что вы планируете вставить, если в Action Subject не указано Remove. Тут очень важен синтаксис.
a. Если вы планируете вставить значение из другого заголовка, то требуется указывать просто заголовок. Например: header.from.url.user
b. Если вы планируете использовать внутреннюю переменную, то указывается так же, только внутренняя переменная. Например: param.message.address.dst.address (IP адрес, куда посылается сообщение)
c. Если вы планируете использовать часть, выделенную с помощью регулярного выражения, то через знак $ указывается номер части регулярного выражение. Например: $2
d. Если вы планируете просто вставить определенное значение, то оно указывается в единичных ковычках. Например ‘Vsem Privet!’
e. Если вы планируете комбинировать эти значения, то это делается через знак +. Например: header.from.url.user+$2+’vsem Privet!’.
Давайте приведем пример регулярного выражения. Достаточно часто встречаемая задача, которая встает передо мной, это в случае переадресованного номера (как в приведенном примере), надо перенести номер из поля history-info в поле From. То есть задача следующая:
1. Перенести в поле From
2. Удалить поле History-info.
Как это делается
Так как AudioCodes не разбирает поле History-info, то выделить номер можно только с помощью регулярного выражения. Строим регулярное выражение для того, чтобы выделить номер из заголовка:
History-Info: <sip:4952345678@20.21.22.23?reason=Forward>
Выделять требуется без учёта имени заголовка. Пример такого регулярного выражения будет
^(<sip:)(.*)(@)(.*)
Требуемый номер будет вторым параметром в данном регулярном выражении. То есть нам требуется вставить значение $2.
Пример такого выражения:
Manipulation Set ID: 1
Message Type: invite
Condition: header.history-info regex ^(<sip:)(.*)(@)(.*)
Action Subject: header.from.url.user
Action Type: Modify
Action Value: $2
Так как далее нам надо удалить поле Histroty-info, то надо создать еще одно правило в рамках того же Manipulation Set ID
Manipulation Set ID: 1
Message Type: invite
Condition: header.history-info exists
Action Subject: header.history-info
Action Type: Remove
Далее просто надо этот Set ID применить как исходящее правило для соответствующей IP Group. После чего на выходе мы получим сообщение следующего вида:
INVITE sip:84951234567@10.11.12.13:5060;transport=udp SIP/2.0
Via: SIP/2.0/UDP 10.11.12.13:5060;branch=z9hG4bK-2342-1C21439
To: <sip: 84951234567@sip.sp.com;user=phone>
From: «Ivanov» <sip: 4952345678@sip.sp.com;user=phone>;tag=26814-XM-09a664f9-77e583465
Allow: UPDATE,REFER,INFO
Call-ID: 26814-TO-09a664f8-0a52daf11@sip.sp.com
Contact: <sip:13.12.11.10:5060>
Content-Type: application/sdp
CSeq: 157771616 INVITE
Max-Forwards: 29
User-Agent: GW_SIP
Content-Length: 258
v=0
o=cp10 139660536057 139660536057 IN IP4 13.12.11.10
s=SIP Call
c=IN IP4 13.12.11.10
t=0 0
m=audio 31854 RTP/AVP 8 0 18
b=AS:80
a=rtpmap:8 PCMA/8000/1
a=rtpmap:0 PCMU/8000/1
a=rtpmap:18 G729/8000/1
a=fmtp:18
annexb=no
a=ptime:20
a=sendrecv
Зачастую стоит вопрос в том, чтобы при манипуляции использовать какие-то переменные, которых нет в SIP сообщении, например, удаленный IP адрес. В этом случае требуется использовать внутренние переменные, такие как
Param.message.address.dst.address – Удаленный IP адрес, на который отправляется сообщение SIP.
Все внутренние переменные описаны в документации, на которую я ссылался до этого.
Так же есть возможность переносить параметры из одного сообщения SIP в другое, предварительно сохранив их в переменные. Данные примеры в данной статье рассматривать не буду.
Отдельно стоит заметить, что данное правило можно применить не только на вариант SBC, но и для голосового шлюза AudioCodes, правда с ограничением, что правило будет работать только для сообщений invite. Для этого требуется так же создать необходимый Manipulation SetID и применить его как входящее или исходящее правило, используя параметр GWOutboundManipulationSet и GWInboundManipulationSet соответственно.
Автор: Victor_AC