5 авг. 2008 г.

Комментарий-заметка к статье от 6 июля 2008 г.

По просьбе читателя хотел было сначала попробовать описать подход Asterisk-Java в виде комментария к предыдущей статье "Модель разработки телекоммуникационных сервисов с использованием IP PBX Asterisk", но в конце концов решил оформить это небольшой заметкой.
Честно говоря, пособием при реализации описанного в статье подхода (использование PBX Asterisk в качестве платформы разработки телекоммуникационных сервисов) был «немногословный» сайт asterisk-java.org с его Asterisk-Java tutorial и API reference, а также www.voip-info.org. И, по сути, данная статья является небольшим пересказом вышеназванных ресурсов применительно к коду Agi-прокси из вышеназванной статьи.
Проект Asterisk-Java предоставляет возможности взаимодействия Asterisk с java-приложениями, выполняющимися на том же сервере или удаленно. Под взаимодействием понимается, во-первых, выполнение java-приложения при наступлении телекоммуникационного события (звонка), а во-вторых, управление и изменение состояния Asterisk непосредственно из java-приложений. В первом случае API Asterisk позволяет описывать обработку звонков (читай dialplan) с помощью высокоуровневых средств (The FastAGI protocol). Во втором случае используется Manager API. Отличие первого подхода от второго заключается в том, что при использовании FastAGI взаимодействие с java-приложением инициируется со стороны Asterisk, а при взаимодействии через Manager API необходимо из самого java-скрипта установить соединение с Asterisk и выполнять действия (ManagerActions), получать ответы (ManagerResponses) и обрабатывать события (ManagerEventListener) от сервера Asterisk.

В Agi-прокси используется и FastAGI (параметры звонка попадают в AgiProxyScript, а затем в web-сервис) и Manager API (при переадресации вызова выполняется фактически звонок в Asterisk).

FastAGI – набор java-классов, на основе которых реализуется AGI-скрипт.
AGI-java-скрипт выполняется сервером Asterisk в соответствии с dialplan, описанном в extensions.conf. Напомню, что обычно extensions.conf располагается в /etc/asterisk/. Итак, например, строка в extensions.conf

exten => 1300,1,Agi(agi://localhost/agiproxy.agi)


предписывает серверу Asterisk при вызове номера 1300 выполнить скрипт с названием agiproxy.agi. Название agiproxy.agi является маппингом на реальное имя class-файла, реализацию AGI-скрипта. Непосредственно маппинг прописывается в файле /var/lib/asterisk/agi-bin/fastagi-mapping.properties и может иметь, например, следующую строку:

agiproxy.agi = AgiProxyScript

где, AgiProxyScript – файл /var/lib/asterisk/agi-bin/AgiProxyScript.class.


Как видно из рисунка, запуск AGI-скрипта выполняется через AgiServer, java-класс из пакета Asterisk-Java реализующий AGI поверх протокола TCP/IP. По сути, Asterisk является своеобразным контейнером для AGI-скриптов, в некоторой степени аналогичным web-контейнеру.
Из исходного кода Agi-прокси видно, что в классе java-скрипта должен быть реализован метод service с двумя параметрами. В первом параметре типа AgiRequest приходят данные от Asterisk, такие как CallerIdName – имя абонента, CallerIdNumber – номер абонента, Extension – название расширения и т.д. На основе этих параметров и осуществляется поиск (в удаленной JSP) команд, которые необходимо выполнить в Asterisk (фактически, это формирование dialplan). Через второй параметр - интерфейс AgiChannel java-приложение получает доступ к командам Asterisk. В тестовом примере AgiProxyScript наследует от BaseAgiScripts, который в свою очередь реализует интерфейсы AgiChannel и AgiScript. Это означает, что AgiProxyScript имеет непосредственный доступ к командам Asterisk – answer(), hangup(), streamFile() и т.д. Одной из команд, которая выполняется в демонстрационном AgiProxyScript является переадресация вызова на указанный номер абонента. Однако такой команды в AgiChannel не предусмотрено, и данная возможность предоставляется через Manager API. В этом случае из java-приложения устанавливается TCP/IP соединение с Asterisk (по умолчанию порт 5038), используя имя пользователя и пароль согласно прописанным значениям в файле manager.conf. Получение соединения (ManagerConnection) выполняется через фабрику ManagerConnectionFactory. Перед использованием полученного соединения необходимо выполнить login(), при завершении - logoff(). Взаимодействие с Asterisk через Manager API сводится с отправке в Asterisk действий (с помощью классов-реализаций интерфейса ManagerAction), получении ответов (в виде интерфейса ManagerResponse) и обработке приходящих событий (реализовав интерфейс ManagerEventListener) от Asterisk. Так в AgiProxy перед выполнением переадресации создается соединение (в статусе ManagerConnectionState.INITIAL):

ManagerConnectionFactory factory = new ManagerConnectionFactory("hostname", "username", "password");
ManagerConnection managerConnection = factory.createManagerConnection();

затем

managerConnection.login();

соединение переводится в статус ManagerConnectionState.CONNECTED и готово к взаимодействию.
Непосредственно переадресация на номер 500:

RedirectAction action = new RedirectAction(
getChannel(), aGIRequest.getContext(), “500”, new Integer(1)); managerConnection.sendAction(action);


В конце всего:

managerConnection.logoff();


Отмечу, что и FastAGI и Manager API посылают команды в Asterisk в строковом виде, но в FastAGI это выполняется через метод buildCommand() классов реализующих интерфейс AgiCommand (AnswerCommand, StreamFileCommand, HangupCommand…), а в Manager API - через интерфейс ActionBuilder.

И пару слов о процессе компиляции скрипта и запуске AgiServer. В простейшем случае после написания скрипта в /var/lib/asterisk/agi-bin/ должны находиться следующие файлы:
- библиотека Asterisk-Java, на момент написания статьи asterisk-java-0.3.1.jar
- файл маппинга fastagi-mapping.properties
- исходный файл AGI-скрипта, например HelloAgiScript.java
Для компилирования Java-скрипта используйте команду следующего вида (JDK должна быть установлена):

javac -cp Asterisk-Java-0.3.1.jar HelloAgiScript.java


После этого в /var/lib/asterisk/agi-bin/ появиться еще один файл - HelloAgiScript.class.
Запустить AgiServer можно выполнив следующую команду (Asterisk должен быть уже запущен):

java -cp Asterisk-Java-0.3.1.jar:. org.asteriskjava.fastagi.DefaultAgiServer

Не знаю на сколько широко и доходчиво я раскрыл концепцию проекта Asterisk-Java, так что буду рад поправкам, ссылкам и комментариям.

2 комментария:

123 комментирует...

It was rather interesting for me to read this post. Thank author for it. I like such topics and everything that is connected to this matter. I definitely want to read more on that blog soon.
Alex
Phone jammers

petrenkov комментирует...

Pretty interesting place you've got here. Thanx for it. I like such topics and anything connected to them. I would like to read more soon.

Truly yours
Darek Wish