Позвонил мне тут один хороший друг, и поинтересовался на тему организации CallBack на сервере Asterisk. Задача мне показалась весьма простой, и ее реализация, в моем понимании, должна занимать строчек 20 кода :) Немного погуглив и поигравшись с *, оказалось, что все проще чем кажется.
Итак, хочется нам сделать такой механизм. Звоню с мобильного в офис, звонок обрывается, и офис перезванивает мне (ну а дальше, уж кому что нужно. хотите с секретарем соединяйтесь, хотите исходящий вызов делайте)

Как же это работает? А очень просто! Сначала напишем диалплан для определения номера нашего мобильного.

Сразу усложним задачу, пусть мобильных будет 2: 9101234567 и 9201234567
[IncomingCall]
exten => s,1,GotoIf($["${CALLERID(num)}" = "9101234567"]?callback)
exten => s,n,GotoIf($["${CALLERID(num)}" = "9201234567"]?callback)
exten => s,n,Goto(normal)
exten => s,n(callback),System(/etc/asterisk/scripts/callback 8${CALLERID(num)} &)
exten => s,n,Hangup
exten => s,n(normal), тут начинается обработка входящих вызовов...

Замечательно. Теперь позвонив с мобильного Asterisk инициирует работу скрипта /etc/asterisk/scripts/callback и положит трубку. Именно этот скрипт и заставит Asterisk перезвонить нам.
Для инициирования исходящего вызова с * достаточно положить .call файл в папку /var/lib/asterisk/outgoing, именно это и делает наш скрипт:
#!/bin/sh
sleep 10
NUMBER=$1
echo "Channel: Local/$NUMBER@InternalCall
MaxRetries: 1
RetryTime: 10
WaitTime: 20
Context: InternalCall
Extension: 100
Priority: 1
AlwaysDelete: Yes" >/var/spool/asterisk/tmp/$NUMBER
mv /var/spool/asterisk/tmp/$NUMBER /var/spool/asterisk/outgoing/$NUMBER

Скриптик просто до нельзя. При старте ждет 10 секунд, после чего создает call файл для исходящего вызова. Как вы уже заметили, в параметре Channel я не указывал напрямую канал и экстеншен, а использовал канал Local. Дело в том, что если указывать напрямую канал SIP,H323, и т.д., то Asterisk не создает CDR запись :) Но это легко обходится указанием экстеншена и контекста для канала Local. Есть еще один очень важный момент! Ввиду того, что сервер Asterisk может прочитать эти файлы в любое время (например, когда он еще записан только наполовину), не создавайте их непосредственно в директории, где их читает Asterisk (/var/spool/asterisk/outgoing).

Алгоритм создания call файлов должен быть примерно следующий:
1) создать файл во временной папке (например /var/spool/asterisk/tmp)
2) перенести файл используя команду mv (операция перемещения файла в пределах одного раздела просто перемещает «inode» – указатель на файл – и он появиться в указанной директории уже сразу целиком, что предотвращает ситуацию, когда Asterisk считывает частично записанный файл.)

Параметры вызова в создаваемом call файле устанавливайте по своему усмотрению. Формат файла приведен ниже:

  • Определяем куда и как нужно совершить вызов
    • Channel: Канал, который будет использоваться для исходящего вызова.
    • CallerID: Name CallerID Обратите внимание, что данное поле должно быть именно в таком формате: CallerID: Some Name <1234>
    • MaxRetries: Количество попыток перед тем, как вызов будет считаться неудачным (не включая первую попытку, т.е. 0 = означает совершить 1 попытку вызова). Значение по умолчанию: 0.
    • RetryTime: Количество секунд между попытками вызова, не стоит очень часто ломиться на недоступный телефон. Значение по умолчанию: 300 (5 минут)
    • WaitTime: Количество секунд для ожидания ответа на вызов. Значение по умолчанию: 45.
    • Account: Установка поля “account code”для записи в CDR.
  • Если первый участник вызова ответил, то далее описываем с кем и как его соединить
    • Context: Контекст в файле extensions.conf.
    • Extension: Название екстеншена в extensions.conf..
    • Priority: Номер приоритета для екстеншена, с которого нужно начать выполнение.
    • Set: Установка переменных канала для использования их в логике обработки вызова на заданный екстеншен (например: file1=/tmp/to ).
    • Application: Имя приложения Asterisk, которое необходимо выполнить (используется вместо параметров context, extension и priority).
    • Data: Параметры для запускаемого приложения.
  • Начиная с версии Asterisk 1.4
    • AlwaysDelete: Yes/No – Если время модификации .call файла больше текущего, то этот файл не будет удален.
    • Archive: Yes/No – Переносить или нет .call файл в поддиректорию «outgoing_done» с установленным значением поля «Status: значение», где значение может быть: Completed, Expired или Failed.

Для совершения вызова в .call файле как минимум должно быть определено одно приложение или екстеншен, наряду с названием канала, с которого совершается вызов.

Ну а теперь осталось дописать в наш диалплан контекст InternalCall, который мы использовали в скрипте.

[InternalCall]
exten => 100, 1, Dial(SIP/100)
exten => 100, n, Hangup
exten => _89X., 1, Dial(SIP/${EXTEN}@GW_IP)
exten => _89X., n, Hangup

все :)