Hangup Handlers
Hangup Handlers were added in Asterisk 11
Overview
Hangup handlers are subroutines attached to a channel that will execute when that channel hangs up. Unlike the traditional h extension, hangup handlers follow the channel. Thus hangup handlers are always run when a channel is hung up, regardless of where in the dialplan a channel is executing.
Multiple hangup handlers can be attached to a single channel. If multiple hangup handlers are attached to a channel, the hangup handlers will be executed in the order of most recently added first.
Dialplan Applications and Functions
All manipulation of a channel’s hangup handlers are done using the CHANNEL function. All values manipulated for hangup handlers are write-only.
hangup_handler_push
Used to push a hangup handler onto a channel.
hangup_handler_pop
Used to pop a hangup handler off a channel. Optionally, a replacement hangup handler can be added to the channel.
hangup_handler_wipe
Remove all hangup handlers on the channel. Optionally, a new hangup handler can be pushed onto the channel.
Examples
Adding hangup handlers to a channel
Removing and replacing hangup handlers
In this example, three hangup handlers are added to a channel: hdlr3, hdlr2, and hdlr1. Using the CHANNEL function’s hangup_handler_pop value, hdlr1 is removed from the stack of hangup handlers. Then, using the hangup_handler_pop value again, hdlr2 is replaced with hdlr4. When the channel is hung up, hdlr4 will be executed, followed by hdlr3.
CLI Commands
13 Comments
Gopalakrishnan N
Any example in which scenario can I use multiple handlers, will this help to kill ZOMBIE channels?
Matt Jordan
Channel masquerades are a complex topic that is a result of Asterisk’s bridging architecture. The notion of masquerading, when and how it occurs, has been a major focus in the development of Asterisk 12.
Gopalakrishnan N
Thanks for the reply.
So I can Hangup handlers when the channels moves from one context to other context even though in two different servers right?
Matt Jordan
I’m not sure I understand your question. This has nothing to do with multiple servers or instances of Asterisk.
Does this example help?
If not, I’d suggest asking any further questions on #asterisk-users or on the asterisk-users mailing list. The wiki is not really meant for Q&A.
Gopalakrishnan N
When am using two context and the call control if transferred from one context to other context the hangup handler properly releases the channel from that context and passes to other one.
And sorry for my Q&A, I will back to asterisk-users mailing list if any.
Thanks for your comments. I really appreciate.
ИТ База знаний
Полезно
— Онлайн генератор устойчивых паролей
— Онлайн калькулятор подсетей
— Руководство администратора FreePBX на русском языке
— Руководство администратора Cisco UCM/CME на русском языке
— Руководство администратора по Linux/Unix
Навигация
Серверные решения
Телефония
FreePBX и Asterisk
Настройка программных телефонов
Корпоративные сети
Протоколы и стандарты
Hangupcause в Asterisk и их значения
Самое важное про Hangupcause
Привет, дорогой читатель! На этапе траблшутинга системные администраторы прибегают к просмотру и анализу лог – файлов Asterisk. В статье поговорим про причины отбоя вызова (hangupcause) в Asterisk, как их найти в лог – файле и что они означают.
Продвинутый курс по Asterisk
Концентрат редких знаний, для внедрения Asterisk в крупных предприятиях. Все это мы собрали в одном курсе для тебя.
Поиск Hangupcause
Подключаемся к нашему серверу IP – АТС по SSH. Открываем консоль и вводим следующую команду:
После того, как Вы нашли hangupcause, его необходимо понять. Переходим к следующему шагу – интерпретация.

Все причины отбоя вызова в Asterisk
Ниже, в таблице, мы составили причины отбоя вызова и соответствующие для них коды SIP ответов с небольшим описанием:
Продвинутый курс по Asterisk
Концентрат редких знаний, для внедрения Asterisk в крупных предприятиях. Все это мы собрали в одном курсе для тебя.
My IT-blog
Слава Україні!
hangup
1 = Unallocated number
16 = Normal call clearing
17 = User busy
18 = No user responding (telephone device not connected)
21 = Call rejected
22 = Number changed
27 = Destignation out of order
38 = Network out of order
41 = Temporary failure
SoftHangup — так же пытается завершить канал, Если канала не существует то приложение сообщит об этом.
SoftHangup(Technology/Resource[,options])
options
a: Разорвать все каналы на устройстве, вместо отключения определенного канала(ресурса).
Преобразование ISUP в SIP
1 unallocated number 404
2 no route to network 404
3 no route to destination 420
16 normal call clearing — (*)
17 user busy 486 Busy here
18 no user responding 408 Request Timeout
19 no answer from the user 480 Temporarily unavailable
20 subscriber absent 480 Temporarily unavailable
21 call rejected 403 Forbidden (+)
22 number changed (w/o diagnostic) 410 Gone
22 number changed (w/ diagnostic) 301 Moved Permanently
23 redirection to new destination 410 Gone
26 non-selected user clearing 404 Not Found (=)
27 destination out of order 502 Bad Gateway
28 address incomplete 484 Address incomplete
29 facility rejected 501 Not implemented
31 normal unspecified 480 Temporarily unavailable
(*) ISDN Cause 16 will usually result in a BYE or CANCEL
(+) Если назначение ‘user’ тогда 6xx код может быть выдан вместо 4xx (403 —> 603)
(=) ANSI procedure — в ANSI сетях, 26 переопределен для описания
‘misrouted ported number’. В противном случае cause 26 обычно не используется в ISUP процедурах.
REL с ISDN cause 22 (number changed) в поле диагностики может содержать информацию о новом номере, по которому может быть доступен абонент. Если MGC может обработать эту информацию она ДОЛЖНА быть добавлена в SIP ответ (301) в поле Contact заголовка.
Resource unavailable
Этот тип ошибок обозначает временный сбой. ‘Retry-After’ хидер МОЖЕТ быть добавлен к ответу если уместно.
34 no circuit available 503 Service unavailable
38 network out of order 503 Service unavailable
41 temporary failure 503 Service unavailable
42 switching equipment congestion 503 Service unavailable
47 resource unavailable 503 Service unavailable
Этот тип ошибок говорит о проблеме с запросом
55 incoming calls barred within CUG 403 Forbidden
57 bearer capability not authorized 403 Forbidden
58 bearer capability not presently 503 Service unavailable
available
Service or option not available
65 bearer capability not implemented 488 Not Acceptable Here
70 only restricted digital avail 488 Not Acceptable Here
79 service or option not implemented 501 Not implemented
Invalid message
87 user not member of CUG 403 Forbidden
88 incompatible destination 503 Service unavailable
Protocol error
102 recovery of timer expiry 504 Gateway timeout
111 protocol error 500 Server internal error
Interworking
127 interworking unspecified 500 Server internal error
В Asterisk начиная с 1.8 так же поддерживает ‘use_q850_reason’ опцию для генерации и чтения, если доступно(чтобы бородатые дядьки телефонисты и другие адепты ОКС7 понимали о чем это мы):
400 Bad Request 41 Temporary Failure
401 Unauthorized 21 Call rejected (*)
402 Payment required 21 Call rejected
403 Forbidden 21 Call rejected
404 Not found 1 Unallocated number
405 Method not allowed 63 Service or option unavailable
406 Not acceptable 79 Service/option not implemented (+)
407 Proxy authentication required 21 Call rejected (*)
408 Request timeout 102 Recovery on timer expiry
410 Gone 22 Number changed (w/o diagnostic)
413 Request Entity too long 127 Interworking (+)
414 Request-URI too long 127 Interworking (+)
415 Unsupported media type 79 Service/option not implemented (+)
416 Unsupported URI Scheme 127 Interworking (+)
420 Bad extension 127 Interworking (+)
421 Extension Required 127 Interworking (+)
423 Interval Too Brief 127 Interworking (+)
480 Temporarily unavailable 18 No user responding
481 Call/Transaction Does not Exist 41 Temporary Failure
482 Loop Detected 25 Exchange — routing error
483 Too many hops 25 Exchange — routing error
484 Address incomplete 28 Invalid Number Format (+)
485 Ambiguous 1 Unallocated number
486 Busy here 17 User busy
487 Request Terminated — (no mapping)
488 Not Acceptable here — by Warning header
500 Server internal error 41 Temporary failure
501 Not implemented 79 Not implemented, unspecified
502 Bad gateway 38 Network out of order
503 Service unavailable 41 Temporary failure
504 Server time-out 102 Recovery on timer expiry
504 Version Not Supported 127 Interworking (+)
513 Message Too Large 127 Interworking (+)
600 Busy everywhere 17 User busy
603 Decline 21 Call rejected
604 Does not exist anywhere 1 Unallocated number
606 Not acceptable — by Warning header
(*) В некоторых случаях,SIP шлюзы могут предоставлять полномочия SIP UAS отвергать INVITE когда авторизация неуспешна. Только если шлюз не может аутентифицировать себя он отправляет код 21.
(+) Если возможно SIP шлюз должен отвечать на ошибки и постараться их исправить, попытавшись переустановить сессию.
Когда появляется Warning header в SIP 606 или 488 сообщении, может быть особое представление ISDN cause code в Warning code. ’31 Normal, unspecified’ ДОЛЖЕН по умолчанию использоваться для наиболее распространенных Warning codes. Если Warning code говорит о недоступности канала передачи данных, то рекомендуется использовать cause code ’65 Bearer Capability Not Implemented’.
3. h extension
Позволяет выполнить часть диалплана после того как повесили трубку.
Используется DeadAGI вместо AGI.
Не вызывайте Hangup из h extension.
Когда запускается ‘h’ extension, стороны разговора уже отключены. Нет способа задержать это, и вы не можете читать аудио из канала. Playback() или Background(), не работают!. По существу, единственная вещь которую можно делать в ‘h’ extension это не делать ничего с каналами которые участвовали в разговоре. Нет аудио, нет DTMF итд..
При использовании макросов или Subов нужно создавать свой собственный h extension
Удобно использовать для создания колбека, биллинга, выполнения всяких полезностей(AGI скрипты) итд
4. Hangupcause в Asterisk
После завершения звонка вы можете посмотреть причину завершения звонка несколькими способами, самый простой это с помощью переменной
$ хранит причину завершения вызова(см п.2) Удобно записывать ее значение в CDR, чтобы было проще делать выборку о неуспешных вызовов.
same => n,Set(CDR(userfield)=HC:$
Но это лишь верхушка айсберга. В 11й версии были добавлены обработчики(Hangup Handlers)
Для понимания как они работают разберем пару функций:
HANGUPCAUSE(channel,type) функция выдает код завершения или с точки зрения технологии или причину которую уже интерпретировал атсериск.
аргументы:
channel — Имя канала по которому мы хотим код завершения вызова.
type — какой тип информации хотим получить:
tech — с точки зрения технологии канала.
ast — код интерпретированный астериском.
Пример:
same => n,Noop($
same => n,Noop($
Technology-specific cause information: IAX2 HANGUP (16),
Asterisk Cause Code: Normal Clearing
HANGUPCAUSE_KEYS() Функция выдает список(разделенных запятыми) каналов для которых доступны код завершения вызова(если инициировано несколько одновременных вызовов) и которые потом можно использовать в функции HANGUPCAUSE.
HangupCauseClear() Приложение очищает все коды завершения уникальные только для этого типа канала. Это никогда не делается автоматически(например для новых Dial()ов).
exten => s,1,NoOp()
same => n,Set(CHANNEL(hangup_handler_push)=handler,s,1)
same => n,Dial(SIP/foo,10)
same => n,HangupCauseClear()
same => n,Dial(SIP/bar,10)
same => n,Hangup()
И так, что же такое Hangup Handlers — это специальные саброуты(subroutines), вспоминаем Gosub. Они прикрепляются к каналу и следуют за ним по всему диалплану, в отличии от подлого h, который нужно создавать в каждом контексте((( К каналу можно подцепить несколько обработчиков, и они будут выполняться в порядке их объявления.
!Обработчики выполняются вне зависимости от h. Они могут выполняться до и после h.
!Трансфер, перехват, парковка могут приводить к обработчикам, вспоминаем старую архитектуру ядра астериска, а именно бридж, до 13!
!Hangup handlers могут быть подключены к любому плечу вызова используя pre-dial handlers.
!!Поскольку hangup handlers это саброуты, то они должны использовать Return для возврата.
!!Добавив hangup handler в h или в другой hangup handler мы получим…(расскажите что).
!!hangup handlers, как и h, должны быстро обрабатываться(последовательность отброса плеча вызова). Некоторые протоколы как ISDN и SIP могут не поддерживать чрезмерную задержку при завершении вызова.
Все манипуляции проводим с помощью функции CHANNEL
;навешиваем обработчик
same => n,Set(CHANNEL(hangup_handler_push)=[[context,]exten,]priority[(arg1[. ][,argN])])
;Отключаем обработчик или его заменяем
same => n,Set(CHANNEL(hangup_handler_pop)=[[[context,]exten,]priority[(arg1[. ][,argN])]])
;удаляем все обработчики
same => n,Set(CHANNEL(hangup_handler_wipe)=[[[context,]exten,]priority[(arg1[. ][,argN])]])
команда CLI которая покажет обработчики для всех каналов
core show hanguphandlers all
Некоторые SIP UA могут не отправлять код завершения, в результате будет отображено последнее состояние о котором сообщил UA. Например: SIP 180 Ringing.
Живой пример: звонок на 2 телефона одновременно к SIP/foo и SIP/bar. hangup handler подключен к вызывающему каналу. Парсятся ответы от каналов и вводится 2 вида кода завершения(уникальный для данного типа канала и интерпретированный астериском).
[default]
exten => s,1,NoOp()
same => n,Set(CHANNEL(hangup_handler_push)=handler,s,1)
same => n,Dial(SIP/foo&SIP/bar,10)
same => n,Hangup()
5.hangupsource
Данная переменная канала(CHANNEL(hangupsource)) позволяет отслеживать кто бросил трубку.
Можно выводить ее значение, или сразу писать в CDR.
exten => h,1,Set(CDR(userfield)=$
Механизм hangup handler в Asterisk
Данная статья описывает преимущества использования механизма hangup handler в диалплане в сравнении с использованием экстеншна h.
Механизм hangup handler появился в Asterisk 11 и позволяет выполнять диалплан сразу после завершения вызова на канале. Использование hangup handler в диалплане обладает рядом преимуществ перед использованием экстеншена h. Во-первых, hangup handler срабатывает вне зависимости от того, в каком контексте происходит выполнение диалплана в момент завершения вызова, во-вторых, можно выполнить диалплан при завершении вызова на канале, на котором диалплан не выполняется, и последнее никак нельзя реализовать с помощью экстеншена h. Диалплан в Asterisk выполняется только на канале, инициировавшем вызов, также, приложения диалплана, создающие новые каналы (такие как Dial и Queue), позволяют выполнять диалплан на канале, ответившем на вызов, сразу после ответа. С помощью hangup handler можно выполнить диалплан на канале, ответившем на вызов, также и после завершения вызова на этом канале (при этом канал, инициировавший вызов, может продолжать существовать, например, в результате перевода вызова).
Использование механизма hangup handler:
Для начала подготовим контекст, который hangup handler будет выполнять. Контекст нужно писать таким же образом, как для приложений Gosub и GosubIf:
ARG1 — номер звонившего, ARG2 — номер ответившего (hangup handler позволяет передавать аргументы точно так же, как Gosub и GosubIf)
Данный контекст отправляет с помощью curl информацию о завершении входящего вызова на некий гипотетический хост stats-host.local, собирающий статистику о вызовах.
Диалплан для добавления hangup handler, который выполнит контекст sub-call-from-cid-ended после завершения вызова на текущем канале:
Диалплан для удаления последнего добавленного hangup handler:
same => n,Set(CHANNEL(hangup_handler_pop)=)
Также можно добавить другой hangup handler на место удаляемого;
Так можно удалить все hangup handler, добавленные на текущий канал (на канал можно добавить несколько hangup handler и они будут выполнены по порядку, начиная с последнего добавленного):
Как и в случае с hangup_handler_pop, можно добавить новый hangup handler на место удаляемых:
Пример использования hangup handler
В очереди inbound есть операторы Local/101@from-queue/n и Local/102@from-queue/n. На хост stats-host.local нужно отправлять HTTP-запрос в тот момент, когда оператор принимает вызов, и в тот момент, когда оператор прекращает участвовать в вызове. Вам может показаться, что задачу можно решить с помощью экстеншена h (ведь при вызове оператора выполняется диалплан в контексте from-queue), но если операторы очереди будут переводить полученные вызовы управляемым и неуправляемым переводом с помощью телефона и с помощью сервисных кодов Asterisk, то экстеншен h не всегда будет выполняться в момент завершения вызова оператора очереди. Ниже приведено решение с помощью hangup handler:
Так вызовы попадают в очередь:
[queues]
exten => inbound,1,Answer
same => n,Queue(inbound,t. 300)
same => n,Hangup
Так выглядит вызов оператора из очереди
[from-queue]
exten => _1XX,1,Dial(SIP/$
same => n,Hangup
Контекст, выполняемый в момент ответа оператора
Asterisk, подмена Hangupcause
Решил написать коротенький мануал по вопросу подмены кодов отбоя (они же hangupcause Q.931 ISDN) в Asterisk.
Иногда нам необходимо отдать клиенту код отбоя вне зависимости от того, что нам пришло на другом конце линии. По умолчанию, при указанном экстене ( exten => s,n,HangUp ) астериск шлет 34 код отбоя (в спецификации sip — это код ошибки 503). Задача сводится к следующему — поймать пришедший с плеча Б код, и передать плечу А уже то, что нам надо, согласно нашим условиям. Все это можно уместить в 2 контекста:
Пример
Давайте рассмотрим работающий пример с подробными логами. Имеется 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, есть еще варианты его использования, но мы возьмем для примера этот)
А корректировать мы будем следующие коды:
Схема подключения:
(предварительную настройку sip peers я делать не буду, положим она уже сделана)
Теперь в исходящий контекст [outgoing] для пользователя 101 (sip-клиент) на asterisk в файле extensions.conf добавим наш диалплан:
[outgoing]
exten => _X.,1,Dial(SIP/$
same => n,GoTo(hangup,s,$
[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
486 в 410
484 в 404
502 в 503
Можно в настройках sip.conf в разделе [global] также прописать use_q850_reason=yes, чтобы в пакете с отбоем появилась информация такого вида:
Таким образом Вы можете контролировать, что именно отдаете своим клиентам, и также настраивать логику согласно специфике работы Вашей АТС на базе Asterisk.





