Реализация задержки ответа на вызов в Asterisk

Одно из разрабатываемых нами решений — анализатор прогресса вызова iqAntibot. Развивая данное решения мы сталкиваемся с различными запросами и требованиями к интеграции с call-центрами. При тестировании у одного из клиентов потребовалось минимизировать получение вызовов операторами колл-сцентра, а также в случае если вызов отбит антиботом — не передавать ответ вызова на сервер колл-центра, инициализированвшего вызов и отклонить вызов с конкретным SIP ответом, который будет зафиксирован в статистике КЦ. При этом расширить логику и обработать заголовок Reason в BYE на стороне КЦ нельзя.

Изначально решение казалось простым:

  • Добавляем промежуточный Asterisk между КЦ и Antibot
  • Проигрываем анонс набранному клиенту с помощью опции A(), пр том Asterisk «задержит» ответ вызывающему до момента окончания анонса
  • Если во время проигрывания анонса вызов разорвался, в зависимости от причины, используем нужный параметр в Hangup(), продолжив выполнение после Dial() с помощью опции g()

Изначальный наборосок диалплана выглядел так (но как мы ошибались):

Всё оказалось не совсем так просто (итоговый диалплан зафиксирован в нашей базе знаний), вот те проблемы которые мы решили в процесе выработки решения для клиента:

  • PJSIP не поддерживает Reason с SIP кодом в модуле res_pjsip_rfc3326 (реализован патч)
    • Добавлено получение SIP кода и конвертация его Q.850 код, который в итоге и доступен в переменной HANGUPCAUSE
    • Внимание нужно обратить на то что переменная устанавливается для вызваемого канала, в диплане непосредственно после команды Dial переменная не доступна
    • Данныё модуль ещё можно улучшить передав непосредственно код и описание через функцию HANGUPCAUSE(), возможно сделаем это в будущем.
  • Обнаружили баг, заключающийся в том, что опция g не срабатывает при разрыве соединения во время проигрывания анонса (багрепорт), реализовано обходное решение:
    • Хук на завершение вызываемого канала (также в нём происходит получение HANGUPCAUSE)
    • Хук устанавливается в помощью вызова процедуры при инициализации канала (опция b() в Dial())
    • Используется приложение ChannelRedirect() для переадресации вызывающего канала

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