Решил написать коротенький мануал по вопросу подмены кодов отбоя (они же hangupcause Q.931 ISDN) в Asterisk.

Иногда нам необходимо отдать клиенту код отбоя вне зависимости от того, что нам пришло на другом конце линии. По умолчанию, при указанном экстене ( exten => s,n,HangUp ) астериск шлет 34 код отбоя (в спецификации sip — это код ошибки 503). Задача сводится к следующему — поймать пришедший с плеча Б код, и передать плечу А уже то, что нам надо, согласно нашим условиям. Все это можно уместить в 2 контекста:

[outgoing]
exten => _X.,1,Dial(<SIP|IAX2>/${EXTEN}@trunk,60,g)
same => n,GoTo(hangup,s,${HANGUPCAUSE})

[hangup]
exten => s,<1...127>,HangUp(<нужный нам код Q.931>)

Логика контекстов проста — после окончания вызова Dial переменная HANGUPCAUSE ловит прилетевшее со стороны Б значение, и посредством функции GoTo переходит в контекст hangup на приоритет со значением от 1 до 127. Непосредственно в нем мы указываем — нужна ли нам замена, либо же мы оставляем значение, которое нам пришло. Список соответствий кодов Q931 --> SIP можно посмотреть. К примеру, здесь

Пример


Давайте рассмотрим работающий пример с подробными логами. Имеется 2 сервера Asterisk, один из которых будет «наш», второй — отдающий произвольные коды отбоя, которые нам необходимо корректировать.

Для начала рассмотрим соответствия SIP кодов Asterisk и Q.931, которые мы будем подставлять в наш контекст:

— 403(21 как AST_CAUSE_CALL_REJECTED)
— 404(1 как AST_CAUSE_UNALLOCATED)
— 410(22 как AST_CAUSE_NUMBER_CHANGED)
— 484(28 как AST_CAUSE_INVALID_NUMBER_FORMAT)
— 486(17 как AST_CAUSE_USER_BUSY)
— 502(27 как AST_CAUSE_DESTINATION_OUT_OF_ORDER)
— 503(34 как AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, есть еще варианты его использования, но мы возьмем для примера этот)

А корректировать мы будем следующие коды:

- 403 в 503 (21--->34)
- 486 в 410 (17--->22)
- 484 в 404 (28--->1)
- 502 в 503(27--->34)
- 503 отдаем как есть(34--->34)
- 404 отдаем как есть(1--->1)

Схема подключения:


(предварительную настройку sip peers я делать не буду, положим она уже сделана)



Теперь в исходящий контекст [outgoing] для пользователя 101 (sip-клиент) на asterisk в файле extensions.conf добавим наш диалплан:

диалплан
[outgoing]
exten => _X.,1,Dial(SIP/${EXTEN}@192.168.1.100,60,g)
same => n,GoTo(hangup,s,${HANGUPCAUSE}) ;; значение HANGUPCAUSE является приоритетом в контексте hangup

[hangup]
exten => s,1,HangUp(1)
same => 17,HangUp(22)
same => 21,HangUp(34)
same => 27,HangUp(34)
same => 28,HangUp(1)
same => 34,HangUp(34)

Самое время проверить данный диалплан на практике. Будем инициировать отдачу sip-провайдером нужных нам кодов, чтобы проверить как asterisk их подменяет, согласно указанным правилам. Номер вызываемого абонента не имеет значения (указан шаблон _X.), поэтому звонить будем на 102. Обозначим sip-клиента A, sip-провайдер B, а наш астериск — Т.

Итак, начнем:

403 в 503


B--->T
2016/12/07 14:31:47.864287 192.168.1.100:5060 -> 192.168.1.59:5060
SIP/2.0 403 Forbidden
Via: SIP/2.0/UDP 192.168.1.59:5060;branch=z9hG4bK5d05bcde;received=192.168.1.59
From: <sip:101@192.168.1.59>;tag=as5eed27bb
To: <sip:102@192.168.1.100>;tag=as64678c0b
Call-ID: 228c0daa2ce496dd10d46e9478757bdc@192.168.1.59:5060
CSeq: 102 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Content-Length: 0

T--->A
2016/12/07 14:31:47.864536 172.16.1.1:5060 -> 172.16.1.10:45416
SIP/2.0 503 Service Unavailable
Via: SIP/2.0/UDP 172.16.1.10:45416;branch=z9hG4bK-524287-1---3b6420a969f2c3a5;received=172.16.1.10;rport=45416
From: <sip:101@172.16.1.1;transport=UDP>;tag=a946bd32
To: <sip:102@172.16.1.1;transport=UDP>;tag=as558ab11d
Call-ID: t_H-Dcu8ceIhISoGT7dI9w…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
X-Asterisk-HangupCause: Call Rejected
X-Asterisk-HangupCauseCode: 21
Content-Length: 0

486 в 410


B--->T
2016/12/07 15:01:06.232282 192.168.1.100:5060 -> 192.168.1.59:5060
SIP/2.0 486 Busy here
Via: SIP/2.0/UDP 192.168.1.59:5060;branch=z9hG4bK49adb904;received=192.168.1.59
From: <sip:101@192.168.1.59>;tag=as274a0aaa
To: <sip:102@192.168.1.100>;tag=as0865c714
Call-ID: 133710b7018b6f003e461b7366dc071d@192.168.1.59:5060
CSeq: 102 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Content-Length: 0

T--->A
2016/12/07 15:01:06.232644 172.16.1.1:5060 -> 172.16.1.10:45416
SIP/2.0 410 Gone
Via: SIP/2.0/UDP 172.16.1.10:45416;branch=z9hG4bK-524287-1---ffcd5e1a73cb2616;received=172.16.1.10;rport=45416
From: <sip:101@172.16.1.1;transport=UDP>;tag=769e0625
To: <sip:102@172.16.1.1;transport=UDP>;tag=as4a312af7
Call-ID: TJ49AuSsPy15GbKbIn3KTw…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Content-Length: 0

484 в 404


B--->T
2016/12/07 15:03:42.757761 192.168.1.100:5060 -> 192.168.1.59:5060
SIP/2.0 484 Address incomplete
Via: SIP/2.0/UDP 192.168.1.59:5060;branch=z9hG4bK329498e8;received=192.168.1.59
From: <sip:101@192.168.1.59>;tag=as7feed819
To: <sip:102@192.168.1.100>;tag=as31afa634
Call-ID: 4c129a6b7680fc2f6940c77525a58e48@192.168.1.59:5060
CSeq: 102 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Content-Length: 0

T--->A
2016/12/07 15:03:42.758083 172.16.1.1:5060 -> 172.16.1.10:45416
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 172.16.1.10:45416;branch=z9hG4bK-524287-1---60687a681de37faa;received=172.16.1.10;rport=45416
From: <sip:101@172.16.1.1;transport=UDP>;tag=2303fd45
To: <sip:102@172.16.1.1;transport=UDP>;tag=as6f3c2e31
Call-ID: VPDPD8Wtelh7GfRX5OSnig…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Content-Length: 0

502 в 503


B--->T
2016/12/07 14:46:12.941218 192.168.1.100:5060 -> 192.168.1.59:5060
SIP/2.0 502 Bad Gateway
Via: SIP/2.0/UDP 192.168.1.59:5060;branch=z9hG4bK39ae3e4a;received=192.168.1.59
From: <sip:101@192.168.1.59>;tag=as0d0f21e7
To: <sip:102@192.168.1.100>;tag=as501e30d3
Call-ID: 50cc1fca1b0c8d4807c110ab2621de88@192.168.1.59:5060
CSeq: 102 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Content-Length: 0

T-->A
2016/12/07 14:46:12.941529 172.16.1.1:5060 -> 172.16.1.10:45416
SIP/2.0 503 Service Unavailable
Via: SIP/2.0/UDP 172.16.1.10:45416;branch=z9hG4bK-524287-1---34f25329bb23215d;received=172.16.1.10;rport=45416
From: <sip:101@172.16.1.1;transport=UDP>;tag=0aabc036
To: <sip:102@172.16.1.1;transport=UDP>;tag=as61430d18
Call-ID: pH7WSH9iuRXDNJ0lyRnlGQ…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
X-Asterisk-HangupCause: Destination out of order
X-Asterisk-HangupCauseCode: 27
Content-Length: 0

503


B--->T
2016/12/07 15:05:17.966997 192.168.1.100:5060 -> 192.168.1.59:5060
SIP/2.0 503 Service Unavailable
Via: SIP/2.0/UDP 192.168.1.59:5060;branch=z9hG4bK0c901ae6;received=192.168.1.59
From: <sip:101@192.168.1.59>;tag=as049eed53
To: <sip:102@192.168.1.100>;tag=as5b5775fa
Call-ID: 115e76677306210f6841df276dba9084@192.168.1.59:5060
CSeq: 102 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Content-Length: 0

T--->A
2016/12/07 15:05:17.967354 172.16.1.1:5060 -> 172.16.1.10:45416
SIP/2.0 503 Service Unavailable
Via: SIP/2.0/UDP 172.16.1.10:45416;branch=z9hG4bK-524287-1---a5d67aaf0d62c772;received=172.16.1.10;rport=45416
From: <sip:101@172.16.1.1;transport=UDP>;tag=886e8753
To: <sip:102@172.16.1.1;transport=UDP>;tag=as515af7fd
Call-ID: rd_vI3FHvTGECqLBPqu_mQ…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Content-Length: 0

404


B---T
2016/12/07 15:07:10.270648 192.168.1.100:5060 -> 192.168.1.59:5060
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 192.168.1.59:5060;branch=z9hG4bK70bbffe3;received=192.168.1.59
From: <sip:101@192.168.1.59>;tag=as42b18ba7
To: <sip:102@192.168.1.100>;tag=as4bbccb03
Call-ID: 681fa91b5d0b43d56125561a0a128540@192.168.1.59:5060
CSeq: 102 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Content-Length: 0

T--->A
2016/12/07 15:07:10.271017 172.16.1.1:5060 -> 172.16.1.10:45416
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 172.16.1.10:45416;branch=z9hG4bK-524287-1---4ccc9dc26a7e83a5;received=172.16.1.10;rport=45416
From: <sip:101@172.16.1.1;transport=UDP>;tag=e5ef327c
To: <sip:102@172.16.1.1;transport=UDP>;tag=as4d3749c4
Call-ID: O5xqrboDIZBqx44TJNEmPA…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Content-Length: 0

Можно в настройках sip.conf в разделе [global] также прописать use_q850_reason=yes, чтобы в пакете с отбоем появилась информация такого вида:

Q.850
2016/12/07 15:26:35.746861 46.4.173.59:5060 -> 213.231.39.180:45416
SIP/2.0 503 Service Unavailable
Via: SIP/2.0/UDP 213.231.39.180:45416;branch=z9hG4bK-524287-1---a8e0763fbaad1b3f;received=213.231.39.180;rport=45416
From: <sip:101@46.4.173.59;transport=UDP>;tag=e4923c2b
To: <sip:102@46.4.173.59;transport=UDP>;tag=as6328694d
Call-ID: YhLSgjZP-vgF2rrqlKstcA…
CSeq: 2 INVITE
Server: Asterisk PBX 11.25.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Reason: Q.850;cause=34
Content-Length: 0

Таким образом Вы можете контролировать, что именно отдаете своим клиентам, и также настраивать логику согласно специфике работы Вашей АТС на базе Asterisk.

Спасибо за внимание.
Поделиться с друзьями
-->

Комментарии (7)


  1. xtelekom
    07.12.2016 21:24
    -1

    Для слива обычно нужно


  1. xomiakba
    08.12.2016 12:24

    А еще можно запихнуть соответствия подмены в AstDB, и делать так:

    same => n, Hangup(${DB(Hag/${HANGUPCAUSE})})

    Не будет необходимости лезть в диалплан.

    А в чем практический смыл этого? Есть пример, где понадобилось?


  1. spacewalk
    08.12.2016 13:57

    Пример, когда у Вас несколько транков на провайдеров, и один отдает некорректный отбой — вместо 503/480 отдает 486 (занято), то на следующий транк такой звонок не перейдет. В данной ситуации подмена поможет


    1. xomiakba
      08.12.2016 16:40

      Да? Хм, а мы тут и не в курсе…

      image

      Балансировка по транкам работает и 486 отбоем.

      Asterisk >1.8

      Так что вопрос актуален.


      1. spacewalk
        08.12.2016 21:35

        Я писал про наш пример, когда сам абонент отдает 486 — нет необходимости к нему ломиться с другой линии, поэтому звонок не переходит на другой транк. И иной случай, когда провайдер вместо 503 отдает 486 — тогда необходимо в существующей логике просто подменить код.
        В Вашем случае у Вас настроено иначе, и наш пример не работает


        1. xomiakba
          09.12.2016 13:00

          Выше как раз Ваш пример, звонок идет на АТС в регионе, которая в виду ошибки отдает 486.
          Если обратите внимание, далее звонок идет на тот же регион и на тот же телефон, но через резервную АТС, и в этом случае уже достигает нужного абонента.

          В вашем случае:

          Если провайдер отдает вам 486 ошибочно, и отдает 486 не ошибочно (истиная занятость), то тем более нужно делать перебор безусловный провайдеров — хуже от этого не будет, но количество звонков, отбитых из-за неполадок на линии сведете к 0.Столько раз наступали на эти грабли.


          1. spacewalk
            09.12.2016 13:58

            В нашем случае провайдер отдавал 486 ошибочно постоянно, после того как начал проводить ремонтные работы. Это было выявлено на 100%, и уточнено у него. Поэтому и возникла такая необходимость.
            В остальных случаях согласен, Ваше решение подходит лучше