| Версия 5.2
Введение
Установка
Администрирование
Сеть
Объекты
Почта
Сигналы
Доступ
Услуги
Справочник
Кластеры
Программы
Разное
Лицензирование
Веб Почта
Pronto!
PBX
Программы | Данные | CLI/API | Правила | CG/PL | PBXApp | XIMSS | WebApp | WSSP | Помощники
# Приложения Реального Времени Среды Приложений Иерархия Файлов Среды Управление Средами Модель Приложения Перевод Звонка Мост между Звонками B2BUA CG/PL Приложения Ввод Сигналы Диалог DTMF Медиа Мосты и Миксеры Перевод Звонка Запросы INFO Служебные Запросы Поддерживаемые Форматы Медиа Модуль Приложений Реального Времени CommuniGate Pro обеспечивает инфраструктуру для создания и использования приложений, обрабатывающих различные Сигналы. Приложения Реального Времени используется для обработки голосовых звонков, включая обслуживание голосовой почты, работу авто-секретаря, организацию конференций и т.д. В этих приложениях реализованы функции "IP-PBX", основывающиеся на стандартах Интернет и обеспечивающие альтернативу существующим PBX (АТС, УАТС). Приложение Реального Времени может активироваться при отправке Сигналов определённому пользователю, а некоторые Сигналы могут быть явно направлены на обработку в Приложение Реального Времени. Программное обеспечение Сервера CommuniGate Pro поставляется с несколькими встроенными Приложениями. Эти приложения обладают большими возможностями по настройке и подходят для использования в большинстве "типовых" случаев. Если вы хотите научиться изменять настройки встроенных Приложений и/или вы хотите создавать свои собственные Приложения Реального Времени, то ознакомьтесь с этим разделом.

## Среды Приложений

Среда для Приложений Реального Времени является набором файлов, которые могут включать в себя:

- CGPL файлы с кодом Приложений и кодом модулей.
- VoiceXML файлы с кодом Приложений
- Произвольные служебные файлы - например, записанные заранее медиа файлы.
- Директории с файлами для различных Языков.

Среды разработаны таким образом, что бы они могли поддерживать работу нескольких разных человеческих (разговорных) языков. По умолчанию языком Среды является Английский. Для поддержки других языковых файлов Среда должна иметь языковые директории, названные по имени поддерживаемого в них языка (`french`, `russian`, `japanese` и т.д.).

Языковая директория может содержать такие же файлы, что и Среда, но она не может иметь поддиректорий.

Задача Приложения Реального Времени может выбирать используемый язык. При выборе языка, не являющегося языком по умолчанию, код приложения пытается прочитать файл из Среды Приложения, используя выбранную языковую поддиректорию. Если в языковой поддиректории файл не найден, то запрашивается файл из самой Среды Приложения (то есть, используется язык по умолчанию).

Сервер CommuniGate Pro поставляется со "стандартной" Средой Приложений Реального Времени. Эта Среда содержит некоторые базовые приложения и все файлы, необходимые для нормальной работы этих приложений, а также некоторые полезные разделы кода и медиа файлы.

Каждая система CommuniGate Pro имеет Общую для Сервера Среду Приложения. В установках с Динамическим Кластером CommuniGate Pro также существует Общая для Кластера Среда Приложения. Для того, что бы изменить эти Среды, откройте через Веб Интерфейс Администратора область Домены и пройдите по ссылке PBX.

Каждый Домен CommuniGate Pro имеет свою собственную Среду Приложения. Для изменения этой Среды, откройте через Веб Интерфейс Администратора область Домены, откройте для требуемого Домена его Установки и пройдите по ссылке PBX.

Изменения Среды, Общей для Кластера, а также изменения Среды для Общих Доменов автоматически распространяются на всех членов Кластера.

Так как Домены могут иметь свои собственные Среды Приложений, различные приложения в разных Доменах могут иметь одинаковые имена.

Все файлы Среды Приложений для не ASCII символов должны использовать кодировку UTF-8.

## Иерархия Файлов Среды

Задачи Приложений Реального Времени выполняются "от имени" определённого Пользователя CommuniGate Pro.
Когда Приложению требуется "файл среды" и выбран язык по умолчанию, Сервер ищет этот файл в:

- Среде Домена Пользователя.
- Общей для Сервера Среде (или, если Пользователь находится в Общем Домене) в Общей для Кластера Среде.
- в Стандартной Среде.

Если выбран язык, не являющийся языком по умолчанию, то Сервер ищет этот файл в языковых поддиректориях вышеперечисленных Сред. Если файл не найден в какой-либо из этих директорий, то осуществляется поиск в самих вышеперечисленных Средах. Таким образом, если файл для требуемого языка не был создан, то будет использоваться язык по умолчанию (Английский).

Такая иерархия обеспечивает простую настройку Приложений. Пользователи во всех Доменах могут использовать одинаковые Стандартные или Общие для Сервера Приложения, а Администраторы конкретного Домена могут настраивать эти приложения под свой домен, загружая пользовательские файлы в Среды своего Домена.

## Управление Средами

Веб Интерфейс Администратора имеет страницы для Редактирования Среды Приложений Реального Времени, которые позволяют обслуживать Общие для Сервера, Общие для Кластера Среды Приложений и Среды Приложений для Домена.

Для обслуживания Общих для Сервера и Общих для Кластера Сред, откройте через Веб Интерфейс Администратора область Домены нажмите на ссылку PBX.

Для обслуживания Среды Домена, откройте через Веб Интерфейс Администратора область Домены, выберите требуемый Домен и нажмите на ссылку PBX. Для создания и изменения Среды Приложений Домена Администратор Домена должен обладать правом доступа "Может модифицировать PBX Приложения".

Страница Редактирование Среды содержит список всех "видимых" в этой Среде файлов: тут перечисляются как файлы, непосредственно загруженные в эту конкретную Среду, так и все файлы, загруженные в Среды и используемые как источник "файлов по умолчанию" для этой Среды:

| Имя | Размер | Обновлено
--- | --- | --- | ---
| Help.gif | 155 | 25-Сен-04
default | addressbook.sppi | 5143 | 23-Сен-05
default | voicemail.sppr | 8K | 27-Фев-05
default | failure.wav | 10K | 27-Фев-05
...
default | xfer.wav | 15K | 28-Сен-05
| xonix.wav | 30K | 02-Окт-05

Файлы, непосредственно загруженные в Среду, имеют флажок в столбце Помеченные. Файлы из других Сред, "видимые" в этой Среде, имеют в этом столбце слово `default`.

Вы можете скачать любой файл из Среды, щёлкнув по имени файла.

Вы можете загрузить в Среду файл, нажав на кнопку Browse и выбрав файл, находящийся на вашем компьютере, а затем нажав на кнопку Загрузить Файл.

Вы можете удалить любой из загруженных в Среду файлов, отметив его флажком и нажав на кнопку Удалить Помеченные.

Если вы загружаете в Среду файл с расширением `.sppr` или `.sppi`, то Редактор предполагает, что в этом файле содержится код какой-либо CG/PL программы и пытается скомпилировать этот код.
Если вы загружаете в Среду файл с расширением `.settings`, то Редактор предполагает, что в этом файле содержится словарь и пытается разобрать его.
Если компилятор обнаруживает ошибку, то файл не загружается в Среду, содержимое файла отображается на странице Редактирования, и маркер красного цвета `<--ERROR-->` показывает точное место ошибки.

Сервер помещает используемые файлы Среды Реального Времени во внутренний Кэш. Если вы загружаете файл в любую Среду, то Кэш среды очищается автоматически. Если вы загружаете файл в Среду Общего Домена или в Среду, Общую для Кластера, то изменённый файл автоматически распространяется по всем членам Кластера.

Вы можете загрузить набор файлов, выбрав TAR-архив (файл с именем расширения `.tar`). Например, если у вас есть TAR-архив с созданными ранее Приложениями Реального Времени, вы можете открыть Среду, которую вы хотите изменить и загрузить в неё файл `.tar`. Сервер распакует архив и будет сохранять каждый файл индивидуально, как будто бы они загружались один за одним.

На странице Редактирования содержится также список всех языковых директорий:

Языки
| arabic
| french
| russian

Для создания нового Языка, введите его название и нажмите на кнопку Создать.

Для того, что бы открыть языковую директорию, щёлкните мышкой по её имени. Редактор отобразит имя Языка и ссылку `Наверх`, с помощью которой вы можете вернуться к списку файлов языка по умолчанию.

### CLI/API

Для управления Средами Приложений может использоваться Интерфейс Командной Строки/API. Дополнительную информацию смотрите в разделе Администрирование Приложений Реального Времени.

### Виртуальные Области в Хранилище Файлов

Среда Прилложений может быть изменена при помощи FTP и HTTP клиентов, приложений CG/PL или любых других методов, обеспечивающих доступ к Хранилищу Файлов Пользователя.
Специальные директории `$DomainPXBApp`, `$ServerPXBApp` и `$ClusterPXBApp`обеспечивают доступ к Среде Приложений Общей для Домена, Общей для Сервера, Общей для Кластера.

## Модель Приложения

Приложения Реального Времени запускаются как Задачи. Запуская Приложение, Сервер CommuniGate Pro запускает новую Задачу и указывает ей начать выполнение с `main` - точки входараздела кода указанного Приложения.

Задача Приложения Реального Времени может быть запущена в режиме disconnected, а может являться частью какой-либо одной сессии Реального Времени (такой, как телефонный звонок) с некоторым участником (peer). Участником является любая единица, принимающая участие в коммуникациях Реального Времени, например: SIP телефон, шлюз в ТфОП, удалённое Приложение Реального Времени, взаимодействующее через SIP протокол, локальное Приложение Реального Времени (то есть, некоторая другая Задача).

Если Задача взаимодействует с каким-либо участником в сессии, она может работать в одном из следующих режимов:

`incoming`
  входящая сессия (в телефонной терминологии - звонок, в SIP терминологии - запрос `INVITE`) была направлена Задаче, но Задача ещё не приняла сессию (звонок).
`provisioned`
  входящая сессия была направлена Задаче, Задача ещё не приняла сессию, но уже отправила предварительный ответ вызывающей стороне.
`connecting`
  задача инициировала исходящую сессию (звонок), но сессия еще не была установлена
`connected`
  Задача приняла водящую сессию или Задача установила исходящую сессию.

Задача может как получать от участника Сигналы, так и отправлять Сигналы сама. Сигналы могут использоваться для окончания текущей сессии, изменения параметров сессии и т.д. Некоторые из Сигналов, отправляемые участнику, обрабатываются непосредственно самой Средой для Приложений Реального Времени, тогда как другие Сигналы передаются на обработку Задаче.

Задача Приложения Реального Времени может иметь связанный с ней Медиа Канал. При установлении сессии, Медиа Канал Задачи соединяется с медиа каналом участника.

Задача может использовать свой Медиа Канал для отправки медиа (аудио, видео) данных участнику, а также для записи отправляемых участником медиа данных.

Задача может переключать медиа участника и в каких-нибудь других местах - например, для отделения сервиса музыка при ожидании от других медиа сервисов. При переключении (отключении) медиа, поступающего от участника, Медиа Канал Задачи не может использоваться, но Задача все еще может контролировать участника, отправляя ему Сигналы, а также будет в состоянии получать Сигналы от участника. Задача может переключить (подключать) медиа, поступающее к/от участника обратно, к своему собственному Медиа Каналу.

Медиа Канал создаёт пространство разговора. Задача может присоединять медиа от других участников к собственному Медиа Каналу Задачи. Эта операция создаёт пространство разговора (или конференцию), которая включает в себя собственного участника Задачи и всех участников, чьи медиа присоединены к этой Задаче. Медиа, отправляемое любым участником, находящимся в пространстве разговора, ретранслируется на всех других участников в этом пространстве, используя специальные алгоритмы смешивания данных и параметры, заданные для этого типа медиа.

Задача с присоединённым медиа участника может использовать свой Медиа Канал для одновременной отправки медиа данных как своему собственному участнику, так и всем присоединённым участникам.

### Перевод Звонка

Задачи Приложения Реального Времени могут автоматически обрабатывать запросы на Перевод Звонка.

При получении Задачей запроса REFER (от удалённого клиента или от другой Задачи), она может:

- обработать его автоматически (этот метод используется по умолчанию)
- отвергнуть его
- передать его в приложение

Если Задача настроена на автоматическую обработку запросов REFER, она создаёт новый запрос INVITE и отправляет его на адрес, указанный в поле Refer-To:. В процессе обработки запроса INVITE задача информирует участника о ходе обработки, отправляя запросы NOTIFY.

Если запрос INVITE выполнен успешно, то Задача посылает текущему участнику Сигнал BYE (если только она сама не получила ранее Сигнал BYE от текущего участника) и затем она переключает свои диалоги по обмену Сигналами и Медиа Канал на нового участника.

Сигнал INVITE, инициированный сигналом REFER, может содержать аутентифицирующую информацию. Приложение может указать Задаче:

- аутентифицировать сигнал INVITE как сигнал, приходящий от текущего Пользователя Эта опция используется по умолчанию.
- аутентифицировать сигнал INVITE как сигнал, приходящий от участника (от единицы, отправившей сигнал REFER).
- отвергать сигналы REFER.

Для обработки "сопровождаемого" Перевода Звонка, ядро Приложения Реального Времени определяет все сигналы INVITE, в которых присутствуют поля Replaces. Если данные из диалога, указанные в полях Replaces, соответствуют активному диалогу, установленному в любой Задаче Реального Времени, то сигнал INVITE направляется этой Задаче. Задача посылает текущему участнику сигнал BYE и переключает свой сигнальный диалог на источник этого сигнала INVITE, а также переключает на единицу, отправившую сигнал INVITE, свой Медиа Канал.
Эта обработка происходит автоматически и является прозрачной для приложения, в котором обрабатывается Задача.

### Мост между Звонками

Пара Задач Приложений Реального Времени может построить Медиа Мост. При создании Медиа Моста участники Задачи обмениваются медиа, но каждая Задача оставляет за собой контроль за сигналами, идущими от участника.

Для построения моста:

- приложение некоторой работающей Задачи A использует функцию CG/PL StartBridge для отправки специального события `[bridgeStart]` Задаче B. В запросе содержится описание медиа участника текущей Задачи A.
- запущенное приложение Задачи B получает этот запрос.
- приложение Задачи B использует функцию CG/PL AcceptBridge для построения моста.
- ядро Приложения Реального Времени посылает сигнал re-INVITE участнику Задачи B, переключая его Медиа на Медиа участника Задачи A.
- ядро Приложения Реального Времени посылает событие `[bridgeResponse]` в Задачу A. Это событие содержит описание медиа участника Задачи B.
- в Задаче B завершается операция AcceptBridge и приложение Задачи B продолжает работу.
- когда Задача A получает событие `[bridgeResponse]`, ядро Приложения Реального Времени обрабатывает это событие самостоятельно и не доставляет его в приложение Задачи A.
- ядро Приложения Реального Времени отправляет re-INVITE участнику Задачи A, переключая его Медиа на Медиа участника Задачи B.
- операция StartBridge в Задаче A завершается и приложение Задачи A продолжает работу.

Если между Задачами A и B построен мост, то одна из Задач (в нашем примере - Задача B) может получить от своего участника сигнал re-INVITE. Новое описание медиа в этом сигнальном запросе может попросить Задачу изменить параметры её медиа (приостановить/продолжить, переключить на другой источник медиа и т.д.). Этот сигнал re-INVITE обрабатывается автоматически и не требует участия со стороны работающего приложения Задачи:

- ядро Приложения Реального Времени посылает специальное событие `[bridgeUpdate]` в Задачу A. Это событие содержит новое описание медиа.
- ядро Приложения Реального Времени самостоятельно обрабатывает событие `[bridgeUpdate]` и не доставляет его в работающее Приложения Задачи A.
- ядро Приложения Реального Времени посылает сигнал re-INVITE участнику Задачи A, переключая его на новый источник Медиа участника Задачи B.
- ядро Приложения Реального Времени посылает новое описание медиа участника A (полученное в отклике re-INVITE) Задаче B как специальное событие `[bridgeResponse]`.
- когда Задача B получает событие `[bridgeResponse]`, ядро Приложения Реального Времени обрабатывает его самостоятельно и не доставляет его в приложение Задачи B.
- новое полученное описание медиа Задачи A отправляется участнику B как отклик на начальный сигнал re-INVITE, переключая участника Задачи B на новое медиа участника Задачи A.

Если между Задачами A и B построен мост, то одна из Задач (в нашем примере - Задача A) может получить от своего участника запрос на Перевод Звонка (REFER):

- ядро Приложения Реального Времени формирует сигнал INVITE для Задачи A и отправляет его участнику; в Сигнале содержится описание медиа участника Задачи B.
- сигнал INVITE заканчивается успешно, описание медиа нового участника Задачи A (участника C) получено.
- ядро Приложения Реального Времени автоматически посылает специальное событие `[bridgeUpdate]` в Задачу B с новым описанием медиа участника.
- когда Задача B получает событие `[bridgeUpdate]`, ядро Приложения Реального Времени обрабатывает это событие самостоятельно и не доставляет его в приложение Задачи B.
- ядро Приложения Реального Времени посылает сигнал re-INVITE участнику Задачи B, переключая его на источник Медиа нового участника Задачи A.

Если между Задачами A и B построен мост, то одна из Задач (в нашем примере - Задача A) может получить от своего участника сигнал запроса на Перевод Звонка - INVITE, в котором есть Replaces (доставляемый модулем Signal в зависимости от содержимого полей Replaces):

- ядро Приложения Реального Времени автоматически посылает специальное событие `[bridgeUpdate]` в Задачу B с новыми параметрами медиа участника A.
- ядро Приложения Реального Времени посылает сигнал re-INVITE участнику Задачи B, переключая его на источник Медиа нового участника Задачи A.
- ядро Приложения Реального Времени отправляет отклик INVITE новому участнику Задачи A, с параметрами медиа участника Задачи B, соединяя нового участника Задачи A с медиа участника Задачи B.

Если между Задачами A и B построен мост, то одна из Задач (в нашем примере - Задача A) может разорвать Медиа Мост:

- приложение Задачи A использует функцию BreakBridge CG/PL для того, что бы разорвать Медиа мост.
- ядро Приложения Реального Времени автоматически отправляет специальное событие `[bridgeClose]` в Задачу B и посылает сигнал re-INVITE участнику Задачи A, переключая его на Медиа Канал Задачи A.
- когда Задача B получает событие `[bridgeClose]`, ядро Приложения Реального Времени автоматически отправляет запрос re-INVITE участнику Задачи B, переключая его на Медиа Канал Задачи B.
- ядро Приложения Реального Времени доставляет событие `[bridgeClose]` приложению Задачи B.

Если между Задачами A и B построен мост, то одна из Задач (в нашем примере - Задача A) может получить от своего участника сигнал на отсоединение (BYE), либо участник может прекратить работу по каким-либо другим причинам. В этом случае:

- ядро Приложения Реального Времени автоматически посылает специальное событие `[bridgeClose]` в Задачу B.
- когда Задача B получает событие `[bridgeClose]`, ядро Приложения Реального Времени автоматически отправляет запрос re-INVITE участнику Задачи B, переключая его на Медиа Канал Задачи B.
- ядро Приложения Реального Времени доставляет событие `[bridgeClose]` приложению Задачи B.

Ядро Приложения Реального Времени может создавать Медиа Мост, используя Медиа Канал Задачи как "медиа релей" (ретранслятор медиа).

### B2BUA

Функциональность Моста между Звонками используется в технологии B2BUA. Пара Задач Реального Времени, соединённая через Мост, может работать как "умный прокси": в то время, как участники, соединённые с этими задачами, взаимодействуют напрямую, управляющие сигналы между ними контролируются Задачами и приложения Задач не прекращают свою работу.

## CG/PL Приложения

Приложения Реального Времени могут быть написаны на языке CG/PL.

Если Задача создаётся для обработки входящего звонка, то её выполнение начинается с точки входа `main` указанного CG/PL приложения.

Приложения Реального Времени могут использовать поддерживаемую в CG/PL возможность внешнего объявления. Когда вызывается раздел кода (процедура или функция), объявленный как внешний, то из среды загружается файл с именем раздела кода и расширением `.sppi`. Код программы в этом файле должен содержать раздел кода с указанным именем и требуемым типом (процедуру или функцию).
Код программы в `.sppi` файле может содержать также и другие разделы программы.

В Приложении Реального Времени могут использоваться следующие встроенные процедуры и функции.

### Ввод

`ReadInput(timeOut)`
  Эта функция используется для получения внешних коммуникаций Задачи: символ DTMF (символ тонового набора), введённый участником, сигналы, отправленные участником, а также События, отправляемые как другими Задачами, так и самой системой. Дополнительную информацию смотрите в разделе CG/PL События.
  Значение timeOut должно быть числом, задающим максимальный период ожидания (в секундах). Если значение timeOut является нулём, то функция проверяет наличие уже ожидающих прочтения цифр или событий, не ожидая дополнительное время.
  Функция возвращает:
  - строку с первым символом DTMF из DTMF буфера Задачи. Этот символ удаляется из буфера Задачи.
  - словарь с первым ожидающим Событием. Событие удаляется из очереди Событий Задачи.
  - нулевое значение, если в течении указанного периода времени не был получен DTMF символ или Событие.

При отсоединении участника, Задача получает от системы Событие Disconnect (в словаре этого События отсутствует элемент `.sender`).

`IsDisconnectEvent(input)`
  Эта функция возвращает истину, если значением input является Событие Disconnect.

    //
    // Sample: ReadInput()
    //   Accept an incoming call (stop if it's not possible).
    //   Play the PressPound media file.
    //   Wait for any input for up to 5 seconds.
    //   If the "pound" ("#") symbol was entered,
    //     play the Good media file.
    //   Otherwise,
    //     play the Bad media file.
    //   Stop.
    //
    entry Main is
      if AcceptCall() != null then stop; end if;
      PlayFile("PressPound");
      PlayFile(ReadInput(5) == "#" ? "Good" : "Bad");
    end entry;

### Сигналы

`RejectCall(responseCode)`
  Эта процедура отвергает входящую сессию при условии, что Задача находится в режиме `incoming` или `provisioned`.
  Значением responseCode должно быть числовое значение между 400 и 699. Это число отправляется обратно вызывающей стороне как код Отклика на Сигнал. Если обратно отправляется код 401 и запрос пришёл извне Сервера CommuniGate Pro (через SIP протокол), то модуль SIP сервера добавляет надлежащие поля в отклик, что бы способствовать Аутентификации клиента.
  Задача переводится в режим `disconnected`.
`AcceptCall()`
  Эта функция принимает входящую сессию при условии, если Задача находится в режиме `incoming` или `provisioned`.
  Эта функция возвращает нулевое значение, если сессии принята успешно и Задача переведена в режим `connected`.
  Если сессия не может быть принята, то эта функция возвращает строку с кодом ошибки и Задачи переводятся в режим `disconnected`.

    //
    // Sample: AcceptCall()/RejectCall()
    //   If the current local time is not between 8:00 and 17:00,
    //     reject the call (with the 403 error code) and stop.
    //   Otherwise,
    //     accept the call (stop if it is not possible)
    //     play the Welcome media file and stop.
    //
    entry Main is
      currentTime = TimeOfDay(GMTToLocal(GMTTime()));
      currentHour = currentTime / 3600;
      if currentHour < 8 or currentHour >= 17 then
        RejectCall(403); stop;
      end if;
      if AcceptCall() != null then stop; end if;
      PlayFile("Welcome");
    end entry;

`RedirectCall(newURI)`
  Эта процедура перенаправляет входящую сессию при условии, что Задача находится в режиме `incoming` или `provisioned`.
  Значение newURI должно быть строкой или массивом строк. Входящая сессия перенаправляется на указанный URI и Задача переводится в режим `disconnected`.
`ForkCall(newURI)`
  Эта процедура перенаправляет входящую сессию при условии, что Задача находится в режиме `incoming` или `provisioned`.
  Значение newURI должно быть строкой или массивом строк. Входящая сессия перенаправляется на указанный URI, но текущая Задача остаётся в том же состоянии и впоследствии сможет принять, отвергнуть, перенаправить, отправить промежуточный отклик или подключить другого участника.
`ProvisionCall(startMedia,reliably)`
  Эта функция отправляет промежуточный Отклик на Запрос входящей сессии, при условии, что Задача находится в режиме `incoming` или `provisioned`.
  Если значение startMedia не является нулевым, то создаётся Медиа Канал Задачи, Задача переводится в режим `provisioned` и может использовать операции Медиа Канала (такие как `PlayFile`) для "контроля посылки вызова".
  Если значение reliably не является нулевым, то требуется подтверждение отклика (SIP `PRACK`) и Задача приостанавливается до момента прихода такого подтверждения.
  Эта функция возвращает нулевое значение если отклик был успешно отправлен.
  Если промежуточный отклик не может быть отправлен, то эта функция возвращает строку с кодом ошибки.
`SetProvisionCode(code)`
  Эта функция указывает код для промежуточного Отклика, отправляемого при вызове функции `ProvisionCall`.
  Значенем code должно быть число из диапазона 101..199 (включительно).
  Первоначальным значением кода промежуточного Отклика является 180.

    //
    // Sample: RedirectCall()/ProvisionCall()
    //   Provision the call (stop if it is not possible).
    //   If the current local time is between 12:00 and 13:00,
    //     fork the call to user1 in the same domain.
    //   Play the "PleaseWait" media file.
    //   If the current local time is not between 8:00 and 17:00,
    //     redirect the call to user2 in the same domain, and stop.
    //   Otherwise,
    //   Accept the call (stop if it's not possible).
    //   Play the Welcome media file, and stop.
    //
    entry Main is
      if ProvisionCall(true,true) != null then stop; end if;
      currentTime = TimeOfDay(GMTToLocal(GMTTime()));
      currentHour = currentTime / 3600;
      if currentHour >= 12 and currentHour <= 13 then
        ForkCall("sip:user1@" + MyDomain());
        stop;
      end if;
      PlayFile("PleaseWait");
      if currentHour < 8 or currentHour >= 17 then
        RedirectCall("sip:user2@" + MyDomain());
        stop;
      end if;
      if AcceptCall() != null then stop; end if;
      PlayFile("Welcome");
    end entry;

Обратите внимание: если ожидающий входящий звонок был прерван, то Задача получает события Disconnect и режим задачи изменяется на disconnected.

`SetCallParameters(parameters)`
  Эта процедура устанавливает параметры звонка (диалог INVITE).
  Значение parameters должно быть словарём, содержащим новые параметры звонка. Существующие значения параметров удаляются.
  Для всех запросов диалога используются следующую параметры:
  `Max-Forwards`
    положительное число, используемое для ограничения числа "переходов" ("хопов"), которое может проходить запрос.
  `customIdentity`
    строка, используемая как поле заголовка `P-Asserted-Identity`.
  `Privacy`
    строка или массив строк, которые будут использоваться как поле заголовка `Privacy`.
  `IPSource`
    IP адрес объекта, который переопределяет правила Сервера и явно устанавливает IP адрес источника для исходящих пакетов SIP и локально генерируемого медиа.
  Следующие параметры используются при установлении диалогов:
  `Session-Expires`
    неотрицательное число, задающее время действия сессии по умолчанию (время обновления диалога). Если устанавливается значение, равное нулю, то обновления диалога не происходит.
  Некоторые параметры используются при установлении звонка (функциями `StartCall`, `StartBridgedCall`), а некоторые - при приёме звонка (функцией `AcceptCall`) - смотрите ниже.
`StartCall(destination)`
  Эта функция инициирует исходящую сессию. Задача должна находиться в режиме `disconnected`.
  Значение destination должно быть строкой, содержащий URI, на который отправляется запрос на сессию или значение должно быть словарём, содержащим следущие строковые элементы:
  `""` (пустая строка)
    URI, на который отправляется запрос на сессию.
  `From` (опционально)
    адрес электронной почты, URI или другие данные, используемые в поле `From`. Если они указаны, то используются данные текущего Пользователя.
  `To` (опционально)
    адрес электронной почты, URI или другие данные, используемые в поле `To`. Если они указаны, то используется URI запроса.
  `Call-ID` (опционально)
    строка, используемая для поля `Call-ID` запроса. Если она не указана, то генерируется новый Call-ID.
  Следующие опциональные параметры берутся из словаря destination. Если они отсутствуют (или destination не является словарём), то они берутся из параметров текущего звонка, заданных при помощи процедуры `SetCallParameters`:
  `Expires`
    число, указывающее максимальную продолжительность вызова (в секундах).
  `Тема`
    строка Subject запроса.
  `Remote-Party-Id`
    словарь, с помощью данных которого создается поле `Remote-Party-Id` запроса.
  `Privacy`
    строка, используемая для создания поля `Privacy` запроса.
  `Diversion`
    массив, используемый для создания полей `Diversion` запроса.
  `P-CGP-Private`
    строка, используемая для создания поля `P-CGP-Private` запроса. Это поле может использоваться для передачи произвольных параметров между отправляющей и принимающей Задачами (в одной или разных системах).
  `P-CGP-Local`
    строка, используемая для создания поля `P-CGP-Local` запроса. Это поле может использоваться для передачи произвольных параметров между отправляющей и принимающей Задачами (только в пределах одного сервера или в пределах одного Кластера).
  `Call-Info`
    массив, используемый для создания полей `Call-Info` запроса.
  `Replaces`
    строка или словарь, с помощью которых создается поле `Replaces` запроса. Если используется словарь, то он должен содержать строковые значения `Call-ID`, `fromTag`, `toTag` и логическое значение `early-only`.
  `NoInitSDP`
    если задан этот параметр, то запрос на установление звонка не содержит Медиа Канал SDP.
  `mediaRelay`
    если задан этот параметр, то для звонка всегда используется Проксирование Медиа.
  Эта функция возвращает строку с кодом ошибки, если исходящий вызов не может быть инициирован.
  Если исходящий вызов был успешно инициирован, то функция возвращает нулевое значение и Задача начинает получать от системы События, возникающие во время звонка: ноль или больше Событий с промежуточными откликами, за которым следует одно Событие с финальным откликом.
  Если исходящая сессия задача была успешно установлена, то Задачи получает Событие с финальными откликом без параметров.
  Если исходящая сессия задача не была успешно установлена, то Задача получает Событие с финальными откликом с параметром - строкой с кодом ошибки.
`IsCallProvisionEvent(input)`
  Эта функция возвращает истину, если значением input является Событие с промежуточным откликом на вызов. В противном случае функция возвращает нулевое значение.
`IsCallCompletedEvent(input)`
  Эта функция возвращает истину, если значением input является Событие с финальным откликом на Звонок. В противном случае функция возвращает нулевое значение. Если Задача получает Событие с финальным откликом, то процесс обработки сигналов вызова завершается. Если Событие имеет параметр, то звонок заканчивается неудачно; в этом случае в параметре содержится строка с кодом ошибки.
`CancelCall()`
  Если у Задачи имеется ожидающий исходящий вызов (инициированный при помощи функции StartCall), то эта процедура прекращает выполнение этого вызова (при этом Задача не получит События с финальным откликом).
`Disconnect()`
  Эта процедура заканчивает активную сессию (если есть) и Задача переводится в режим `disconnected`.

    //
    // Sample: StartCall()/Disconnect()
    //   Accept an incoming call (stop if it's not possible).
    //   Remember the caller URI.
    //   Play the CallBack media file.
    //   Disconnect();
    //   Call the caller back (stop if it's not possible).
    //   Play the IamBack media file, and stop.
    //
    entry Main is
      if AcceptCall() != null then stop; end if;
      fromWhom = RemoteURI();
      PlayFile("CallBack");
      Disconnect();

      if StartCall(fromWhom) != null then stop; end if;

      loop
        input = ReadInput(3600);
      exitif not IsCallProvisionEvent(input);
        null;
      end loop;

      if not IsCallCompletedEvent(input) or else
         input.parameter != null then stop; end if;

      PlayFile("IamBack");
    end entry;

`IsConnected()`
  Эта функция возвращает истину, если Задача находится в режиме `connected`.
`IsHalfConnected()`
  Эта функция возвращает истину, если Задача находится в режиме `connected` или `provisioned`.
`PendingRequestData(fieldName)`
  Эта функция возвращает элемент данных из ожидающего входящего запроса.
  Если запрос является ожидающим, то функция возвращает следующие данные, в зависимости от значения fieldName, которое должно являться строкой:
  `Call-ID`
    Функция возвращает строку со значением Call-ID запроса.
  `From`, `To`, `Remote-Party-Id`
    функция возвращает словарь, если такое поле существует в этом запросе. В словаре содержатся следующие элементы:
    `""` (элемент с пустой строкой-ключом)
      адрес (в форме username@domain)
    `@realName`
      строка, в которой содержится часть адреса "отображаемое имя" (Display Name)
    `tag`
      параметр "tag" из URI
    `@uri-params`
      словарь с другими параметрами URI.
    Все элементы, кроме элемента адрес, являются опциональными.
  `Route`, `Record-Route`, `Diversion`, `Via`, `Path`, `Supported`, `Require`, `Proxy-Require`, `Privacy`
    функция возвращает массив, содержащий одну или более строк со значениями полей. Если никаких значений не существует, то функция возвращает нулевое значение.
  `CSeq`
    функция возвращает число - значение числовой части поля CSeq
  `Max-Forwards`
    функция возвращает число - значение поля Max-Forwards.
  `User-Agent`, `Reason`, `Privacy`, `P-CGP-Private`, `P-CGP-Local`
    функция возвращает строку - значение поля. Если поле отсутствует, то функция возвращает нулевое значение.
  `Accept`
    функция возвращает массив, содержащий 2 строки для каждого значения поля: принятый тип содержимого (content type) и принятый подтип содержимого (content subtype). Если поле отсутствует, то функция возвращает нулевое значение.
  `Foreign-Asserted-Identity`
    функция возвращает массив, содержащий один или более словарь для каждого поля запроса `P-Asserted-Identity`. Каждый словарь содержит такие же элементы, как и поле `From` словаря.
  Если нет никакого ожидающего запроса, то функция возвращает нулевое значение.
`PendingRequestExData(fieldName)`
  Эта функция возвращает нестандартный элемент данных ожидающего входящего запроса.
  Значение fieldName должно быть строкой. В ней указывается имя нестандартного поля запроса.
  Если запрос является ожидающим, то функция возвращает строку, в которой содержаться данные из указанного поля запроса.
  Если нет никакого ожидающего запроса, то функция возвращает нулевое значение.
`SetForeignCredentials(authName,password)`
  Эта процедура задаёт полномочия (аутентифицированное имя пользователя и пароль), используемое исходящими запросами, отправленными этой Задачей.
  Значения authName и password должны быть строками, в противном случае полномочия сбрасываются.
`SetReferMode(mode)`
  Эта процедура используется для указания способа обработки Задачей запросов REFER и INVITE/replaces. Параметр mode должен быть строкой:
  `self`
    аутентифицировать исходящие сигналы как приходящие от текущего Пользователя
  `peer`
    аутентифицировать исходящие сигналы как приходящие от участника Задачи (то есть, от отправителя сигнала REFER).
  любое другое значение
    запретить обработку запросов REFER и INVITE/replaces
`SetTransferReportMode(mode)`
  Эта функция функция устанавливает флаг функции для отчётов о переводе звонка.
  Если значение mode является нулевым, то Событие при переводе звонка другому участнику не отправляется.
  В противном случае Задача получает специальное Событие CallTransferred, когда она переводится на другого участника.
  Функция возвращает предыдущее значение этого флага функции.
  При создании новой Задачи, её отчёты о переводе звонков выключаются (флаг функции устанавливается в нулевое значение).
`IsCallTransferredEvent(input)`
  Эта функция возвращает истину, если значением input является Событие CallTransferred. В противном случае функция возвращает нулевое значение.
`SetBridgeBreakMode(mode)`
  Эта процедура используется для указания способа реакции Задачи на разрыв моста другой задачей. Параметр mode должен быть строкой:
  `disconnect`
    сигнал BYE отправляется участнику Задачи и Задача переводится в режим disconnected.
  `сохранить`
    если Задача не имеет Медиа Канала, он создаётся и участник Задачи переключается на этот канал.

### Диалог

`RemoteURI()`
  Эта функция возвращает строку с URI участника (взятых из адресов диалога From/To). Если сессия отсутствует, функция возвращает нулевое значение.
`LocalURI()`
  Эта функция возвращает строку с URI Задачи.
`IncomingRequestURI()`
  Эта функция возвращает строку с URI ожидающего входящего запроса INVITE. Если ожидающий входящий запрос INVITE отсутствует, то функция возвращает нулевое значение.
`RouteLocalURI(uri)`
  Эта функция пытается провести Маршрутизацию для адреса электронной почты, задаваемого URI. Если URI не может быть разобран или для адреса из URI невозможно провести маршрутизацию, или он маршрутизируется в адрес, не являющийся локальным (то есть, адрес электронной почты принадлежит другой системе), то функция возвращает нулевое значение. В противном случае функция возвращает адрес электронной почты того пользователя CommuniGate Pro, на которого указывает адрес из URI после проведения маршрутизации.
  Эта функция позволяет вам корректно обрабатывать все Переадресаторы, Псевдонимы и другие методы маршрутизации, используемые в CommuniGate Pro.
`RemoteIPAddress()`
  Эта функция возвращает объект типа IP адрес, с которого был получен или на который был отправлен запрос на установление сессии. Эта пара IP адрес/порт является фактическим адресом участника или адресом прокси, используемого для ретрансляции сигналов участника.
`RemoteAuthentication()`
  Эта функция возвращает либо нулевое значение, если запрос на начало сессии не был аутентифицирован, либо строку с адресом электронной почты аутентифицированного пользователя.

### DTMF

Каждая Задача имеет строку буфера DTMF (буфера тонового набора). При получении символа DTMF либо в Запросе INFO, либо в пакете медиа (через Медиа Канал), символ добавляется в этот буфер.

`DTMF()`
  Эта функция возвращает строку с текущим содержанием буфера DTMF. Буфер DTMF не изменяется. Обычно эта функция не используется; используйте вместо неё функцию `ReadInput()`.
`ClearDTMF()`
  Эта процедура очищает буфер DTMF.
`SetInterruptOnDTMF(arg)`
  Эта функция устанавливает флаг, прерывающий воспроизведение медиа при получении символов DTMF.
  Значение arg задаёт новое значение флага: если его значение является нулевым, то получение символов DTMF не прерывает воспроизведение медиа, в противном случае получение символов DTMF прерывает воспроизведение медиа.
  При создании Задачи значение этого флага устанавливается в значение истина.
  Функция возвращает предыдущее значение этого флага.
`SendDTMF(symbol)`
  Эта функция посылает участнику символ DTMF.
  Значение symbol должно быть строкой, в которой содержится 1 символ DTMF.
  Эта функция возвращает нулевое значение, если символ был отправлен; в противном случае возвращается строка с кодом ошибки.

    //
    // Sample: ReadInput()/SendDTMF()
    //   Accept an incoming call (stop if it's not possible).
    //   Wait for an input for 10 seconds. If no input - stop.
    //   If a digit is entered
    //      play that digit, and send it back.
    //      (using "0" ... "9" files)
    //   If a star ("*") is entered,
    //     wait for a digit (for 3 seconds)
    //     and play the digit number square (2 digits)
    //   If a pound ("#") is entered or the Peer
    //     has disconnected, or any Event was sent, stop.
    //
    entry Main is
      if AcceptCall() != null then stop; end if;
      loop
        input = ReadInput(10);
    	if input == "*" then
    	  input = ReadInput(3);
    	  if IsString(input) and input != "#" then
    	    input = "*" + input;
    	  end if;
    	end if;
      exitif not IsString(input) or input == "#";
        if Substring(input,0,1) != "*" then
    	  PlayFile(input);
    	  void(SendDTMF(input));
    	else
    	  input = Number(Substring(input,1,1);
    	  product = input *  input;
    	  PlayFile(String(product/10));
    	  PlayFile(String(product%10));
    	end if;
      end loop;
    end entry;

### Media

`PlayFile(fileName)`
  Эта процедура запрашивает файл из Среды Приложения и воспроизводит его. В строковом параметре fileName задаётся имя файла. Если указанное имя файла не содержит расширения файла, то к нему добавляются поддерживаемые расширения и попытка повторяется.
  Файл должен содержать медиа данные в одном из поддерживаемых форматов.
  Воспроизведение останавливается или прерывается, если сессия заканчивается или буфер DTMF не пуст (если только Прерывание при DTMF не было выключено), или если Задаче было направлено Событие.
`PlayFileInLoop(fileName,msec)`
  Эта процедура подобна процедуре PlayFile.
  Значение msec должно быть числом.
  Эта процедура воспроизводит указанный файл в течении msec миллисекунд, повторяя, если время его воспроизведения короче, чем указанный период, файл с начала. Если параметр msec имеет отрицательное значение, то файл воспроизводится в цикле без ограничения времени.
  Воспроизведение останавливается или прерывается, если сессия заканчивается или буфер DTMF не пуст (если только Прерывание при DTMF не было выключено), или если Задаче было направлено Событие.
`Play(waveData)`
  Эта процедура воспроизводит блок данных waveData.
  Блок данных должен содержать медиа данные в одном из поддерживаемых форматов.
  Воспроизведение останавливается или прерывается, если сессия заканчивается или буфер DTMF не пуст (если только Прерывание при DTMF не было выключено), или если Задаче было направлено Событие.
`PlayInLoop(waveData,msec)`
  Эта процедура такая же, как и процедура Play, но она может воспроизводить медиа данные в цикле, так, как это делает процедура PlayFileInLoop.
`GetPlayPosition()`
  Эта функция возвращает число - часть медиа (в миллисекундах), воспроизведённое последней операций `PlayFile`, `PlayFileInLoop`, `Play` или `PlayInLoop`.
  Если медиа воспроизводилось по кругу, то длиной воспроизведённой части является продолжительность воспроизведения последнего "круга": так, если 3-х секундный отрывок проигрывался по кругу и его воспроизведение было прервано после 7.2 секунд, то функция возвращает значение 1200.
  Если последняя операция Play* не возспроизводила звук (из-за того, что буфер тонового набора DTMF был не пустой или в очереди отсутствовало Событие), то функция возвращает либо 0, либо отрицательное значение.
`SetPlayPosition(arg)`
  Эта процедура указывает непосредственно следующей за ней операции `Play*` начинать воспроизведение не с начала фрагмента.
  Значение arg должно быть неотрицательным числом. Оно указывает количество милисекунд, которое должно быть пропущено до начала воспроизведения медиа операций Play*.
`IsPlayCompleted()`
  Эта функция возвращает значение истина, если медиа было полностью проиграно последней операций `Play*`. Если проигрование медиа было прервано, то функция возвращает нулевое значение.
`Record(timeLimit)`
  Эта функция записывает входящие аудио данные. Значение timeLimit должно быть положительным числом, задающим максимальную продолжительность воспроизведения в секундах.
  Запись останавливается или прерывается, если сессия заканчивается или буфер DTMF не пуст, или если Задаче было направлено Событие.
  Функция возвращает либо нулевое значение, если запись была остановлена, либо блок данных с записанным аудио в формате `WAV`.
`SetLocalHold(flag)`
  Эта процедура ставит текущий вызов "на ожидание" (если flag имеет значение истина) или снимает его с ожидания (если flag имеет нулевое значение).
  Эта процедура может использоваться только когда задача находится в режиме connected и медиа мост у участника Задачи участника Задачи отсутствует.
`ReleaseMediaChannel()`
  Эта процедура освобождает Медиа Канал Задачи (и связанные с ним системные ресурсы).
  Эта процедура может использоваться только когда Задача находится в режиме disconnected или у участника Задачи существует медиа мост.

    //
    // Sample: Record()/PlayFile()/Play()
    //   Accept an incoming call (stop if it's not possible).
    //   Play the GreetingIs file.
    //   Read the current prompt from
    //      the MyGreeting.wav file in the Personal Site.
    //   Loop playing the greeting.
    //      if "1" is entered, rewrite the prompt file and quit
    //      if "2" is entered, play "Beep" and record the prompt.
    //
    entry Main is
      if AcceptCall() != null then stop; end if;
      PlayFile("GreetingIs");
      prompt = ReadSiteFile("MyGreeting.wav");
      loop
        if IsData(prompt) then Play(prompt); end if;
        input = ReadInput(10);
      exitif not IsString(input) or else input == "#";
        if input == "1" then
    	  if WriteSiteFile("MyGreeting.wav",prompt) then
    	    PlayFile("Goodbye"); stop;
    	  end if;
    	  PlayFile("Failure");
    	elif input == "2" then
    	  PlayFile("Beep");
    	  prompt = Record(30);
    	else
    	  PlayFile("InvalidEntry");
    	end if;
      end loop;
      PlayFile("GoodBye");
    end entry;

### Мосты и Миксеры

`StartBridge(taskRef)`
  Эта функция посылает специальное Событие StartBridge указанной Задаче, с запросом на приём медиа участника Задачи.
  Значение taskRef должно быть описателем задачи. Он задаёт Задачу, которой отправляется запрос.
  Эта функция возвращает нулевое значение, если указанная Задача успешно перехватила медиа участника Задачи. В противном случае, функция возвращает строку с кодом ошибки.
  Текущая Задача должа находится в режиме `incoming`, `provisioned` или `connected`.
  Текущая задача ставится в ожидающее состояние, требуемая Задача получает специальное Событие StartBridge.
`IsStartBridgeEvent(input)`
  Эта функция возвращает истину, если значением input является Событие StartBridge. В противном случае функция возвращает нулевое значение.
`RejectBridge(input,errorCode)`
  Эта функция отвергает запрос StartBridge.
  Значение параметра input должно быть Событием StartBridge, которое необходимо отвергнуть.
  Значение параметра errorCode должно быть строкой.
  Функция StartBridge в Задаче, которая отправила Событие StartBridge, выходит из состояния ожидания и возвращает строку с кодом ошибки.
  Эта функция возвращает нулевое значение, если ожидающий входящий звонок был успешно отвергнут. В противном случае, функция возвращает строку с кодом ошибки.
`AcceptBridge(input)`
  Эта функция строит Медиа Мост с Задачей, которая отправила Событие StartBridge.
  Значение параметра input должно быть Событием StartBridge, которое необходимо принять.
  Эта функция возвращает нулевое значение, если Медиа Мост был установлен успешно. В противном случае, функция возвращает строку с кодом ошибки.
  Функция StartBridge в Задаче, которая отправила Событие StartBridge, выходит из состояния ожидания. Та функция возвращает нулевое значение, если Мост был установлен; в противном случае возвращается строка с кодом ошибки. Если эта Задача находилась в режиме `incoming` или `provisioned`, звонок принимается и Задача переключается в режим `connected`.

При успешной установке Медиа Моста между парой Задач, медиа их участников соединяются друг с другом. Медиа Каналы Задач отсоединяются от их участников и операции Медиа Каналов (`PlayFile`, `Record` и т.д.) использоваться не могут.
Пока Медиа Мост активен, Задача не может использовать функции `StartBridge`, `AcceptBridge` и `AttachMixer`.

`BreakBridge()`
  Эта функция убирает Медиа Мост, созданный в результате успешного выполнения функции `StartBridge` или `AcceptBridge`.
  Медиа Канал Задачи заново соединяется с медиа каналом участника.
  Задаче, с которой был построен Мост, отправляется специальное событие BreakBridge.
  Эта функция возвращает нулевое значение, если существующий медиа мост был убран успешно. В противном случае, функция возвращает строку с кодом ошибки.
`IsBreakBridgeEvent(input)`
  Эта функция возвращает истину, если значением input является Событие BreakBridge. В противном случае функция возвращает нулевое значение.
  Когда Задача получает Событие BreakBridge, она не должна использовать процедуру BreakBridge(), так как Медиа Мост уже был удалён.

Если Задача отсоединяется от участника, или участник Задачи отсоединяется самостоятельно (штатно или в результате ошибки) и существует активный Медиа Мост, то этот Медиа Мост убирается автоматически.

    //
    // Sample: StartBridge()/AcceptBridge()/BreakBridge()
    //   Accept an incoming call (stop if it's not possible).
    //   Create a new Task to run the Caller code,
    //     and send it an Event with the URI to dial.
    //   Play the PleaseWait media file.
    //   Wait for a StartBridge Event from the Caller Task.
    //   Accept it and loop till the user disconnects.
    //
    //   The Caller code:
    //   Receive a URI to call as an Event from the parent Task
    //   Connect to the URI and play the YouGotACall media file
    //   StartBridge with the parent, loop till the user disconnects
    //
    entry Caller forward;
    procedure ControlBridge() forward;

    entry Main is
      if AcceptCall() != null then stop; end if;

      callerTask = spawn Caller;
      if callerTask == null or else
         SendEvent(callerTask,"dial","sip:internal@partner.dom") != null then
    	PlayFile("Failure");
    	stop;
      end if;

      PlayFile("PleaseWait");
      input = ReadInput(30);
      if not IsStartBridgeEvent(input) or else
         AcceptBridge(input) != null then
    	PlayFile("Failure");
    	stop;
      end if;

      // we have established a bridge
      ControlBridge();
      PlayFile("GoodBye");
    end entry;

    //
    // Caller Task code
    //
    entry Caller is
      // wait for a "dial" event from the main task
      input = ReadInput(30);
      if input == null or input.what != "dial" then stop; end if;

      mainTask = input.sender;

      // Calling the URI specified as the Event parameter
      // If connection failed, send an Event back to the
      //  main task and quit
      resultCode = StartCall(startEvent.parameter);
      if resultCode != null then
        void(SendEvent(mainTask,"result",resultCode));
    	stop;
      end if;

      // wait for any Event other than provisional ones
      loop
        input = ReadInput(3600);
      exitif not IsCallProvisionEvent(input);
      end loop;

      // the parent has sent us "stop" - then we'll die immediately
      if IsDictionary(input) and then input.what == "stop" then stop; end if;

      if not IsCallCompletedEvent(input) or else input.parameter != null then
        void(SendEvent(mainTask,"result","generic error"));
    	stop;
      end if;

      if StartBridge(mainTask) != null then
    	PlayFile("Failure");
    	stop;
      end if;

      // we have established a bridge
      ControlBridge();
      PlayFile("GoodBye");
    end entry;

    //
    // Controlling the peer signaling:
    // while the media is bridged:
    //	exit if the peer hangs up, dials "#"
    //  or if the bridge is removed
    //
    procedure ControlBridge() is
      loop
        input = ReadInput(3600);
      exitif IsBreakBridgeEvent(input) or else
              IsDisconnectEvent(input) or else input == "#";
      end loop;
      void(BreakBridge());
    end procedure;

`AttachMixer(input)`
  Значение параметра input должно быть Событием StartBridge, отправленным этой Задаче.
  Эта функция присоединяет медиа участника Задачи-отправителя к Медиа Каналу этой Задачи.
  Эта функция возвращает нулевое значение, если медиа участника Задачи-отправителя было успешно присоединено к Медиа Каналу этой Задачи. В противном случае, функция возвращает строку с кодом ошибки.
  Функция StartBridge в Задаче-отправителе выходит из состояния ожидания. Функция StartBridge возвращает нулевое значение, если медиа участника Задачи-отправителя было успешно присоединено. В противном случае, эта функция возвращает строку с кодом ошибки.
  Обратите внимание: Если функция `AttachMixer` использовалась в момент нахождения Задачи в режиме disconnected и Задача не имеет Медиа Канала, то для этой Задачи создаётся новый Медиа Канал.
`DetachMixer(taskRef)`
  Эта функция отсоединяет медиа участника указанной Задачи от Медиа Канала этой Задачи.
  Значение taskRef должно быть описателем задачи.
  Функция возвращает нулевое значение, если медиа участника указанной Задачи было успешно присоединено к Медиа Каналу этой Задачи и если это медиа участника было успешно воссоединено с указанной Задачей.
  Указанная Задача получает Событие BreakBridge.
  Функция возвращает строку с кодом ошибки, если медиа участника другой Задачи не может быть отсоединено.
  Значение taskRef может быть описателем задачи. В этом случае медиа участника всех других Задач отсоединяется от Медиа Канала этой Задачи.
`MixerAttached()`
  Эта функция возвращает массив описателей задачи всех Задач, которые соединили свои медиа участников с Медиа Каналом этой Задачи.
  Если этот Медиа Канал Задачи не имеет никакого другого медиа участников других Задач, то эта функция возвращает нулевое значение.
`MuteMixer(taskRef,flag)`
  Эта процедура определяет, должен ли Медиа Канал Задачи игнорировать данные от указанной Задачи.
  Значение taskRef должно быть описателем Задачи. Медиа участника этой Задачи должно быть подключено к Медиа Каналу текущей Задачи.
  Значение taskRef может быть нулевым; в этом случае управляется медиа участника текущей Задачи.
  Значение flag указывает операцию: если flag имеет значение истина, то медиа участника игнорируется; в противном случае Медиа Канал начинает обрабатывать медиа от участника.

Если медиа участника другой Задачи соединено с Медиа Каналом Задачи, то все медиа направляются в единое пространство разговора (в конференцию).

Эта задача не может использовать функции `StartBridge` или `AcceptBridge`.

Обратите внимание: в определённых случаях система может преобразовывать операцию функции `AcceptBridge` в операцию функции `AttachMixer`. Как результат этого, операция `BreakBridge` может использоваться такой Задачей, которая имеет только одно другое медиа участника, подсоединённое к своему Медиа Каналу.

Если Задача отсоединяется от участника или участник Задачи отсоединяется самостоятельно (штатно или в результате ошибки) и существует медиа участника другой Задачи, соединённое с этим Медиа Каналом Задачи, то система отсоединит его автоматически.

`StartBridgedCall(destination,event)`
  Эта функция работает также, как функция `StartCall`, но значение `event` должно быть Событием StartBridge, отправленным в эту задачу входящей Задачей. Задача инициирует вызов, используя описание медиа из данных События (описывающие медиа участника входящей Задачи).
  Промежуточные отклики доставляются в текущую Задачу как События, а также они отправляются входящей Задаче (смотрите ниже).
  Если вызов успешен, то между Задачами строится Медиа Мост, текущая Задача получает Событие с финальным откликом и операция StartBridge во входящей Задаче завершается успешно.
  Если вызов заканчивается неуспешно, то текущая Задача получает Событие с финальным откликом, но входящей Задаче никакого События не посылается. Текущий Задача может либо попытаться осуществить новую операцию StartBridgedCall, либо она может использовать операции AcceptBridge/AttachMixer/RejectBridge для обработки полученного события StartBridge.
  Если входящая Задача закончила выполнение или Задача поставила входящий звонок на ожидание и этот звонок был прерван, то инициированный исходящий звонк прерывается и текущая Задача получает событие BreakBridge.
`SetBridgedProvision(newMode)`
  Эта функция управляет обработкой Событий с промежуточными откликами, ретранслированными текущей Задаче во время выполнения операции StartBridge.
  Если newMode имеет значение истина (значение по умолчанию), то ретранслированные промежуточные отклики ретранслируются участнику при помощи функции ProvisionCall, у которой параметр `reliably` установлен в нулевое значение.
  Если значением newMode является строка "reliably", то ретранслированные промежуточные отклики ретранслируются участнику при помощи функции ProvisionCall, у которой параметр `reliably` установлен в значение истина.
  Если newMode имеет нулевое значение, то ретранслированные промежуточные отклики игнорируются.
  Если значением newMode является число, то оно используется для задания длины очереди промежуточных откликов FIFO. Это очередь используется в тех случаях, когда промежуточные отклики из одной задачи принимаются быстрее, чем они могут быть доставлены участнику. По-умолчанию значением длины очереди является 10.
  Если Задача не находится в режиме `incoming` или `provisioned`, то ретранслированные промежуточные отклики игнорируются.
  Функция возвращает старое значение опции.

### Перевод Звонка

`TransferSupported()`
  Эта функция возвращает истину, если участник поддерживает операции Перевода Звонка; в противном случае функция возвращает нулевое значение.
`TransferCall(destination)`
  Эта функция осуществляет "несопровождаемый" перевод. Задача должна находиться в режиме `connected`.
  Значение destination должно быть строкой, содержащий URI или адрес электронной почты, на который должен быть переведён звонок.
  Если перевод звонка заканчивается неудачно, то функция возвращает строку с кодом ошибки.
  Если перевод звонка заканчивается успешно, то функция возвращает нулевое значение.
  Когда операция завершается, Задача остаётся в режиме `connected`, за исключением ситуации, при которой участник был отключён явно (путём отправки запроса BYE).
`StartTransfer(taskRef)`
  Эта функция посылает специальное Событие StartTransfer указанной Задаче, прося её подключить участников Задачи напрямую.
  Значение taskRef должно быть описателем задачи. Он задаёт Задачу, которой отправляется запрос.
  Эта функция возвращает нулевое значение, если указанная Задача успешно подключила участников. В противном случае, функция возвращает строку с кодом ошибки.
  Текущая Задача должна находиться в режиме `connected`.
  Текущая задача ставится в ожидающее состояние, требуемая Задача получает специальное Событие StartTransfer.
`IsStartTransferEvent(input)`
  Эта функция возвращает истину, если значением input является Событие StartTransfer. В противном случае функция возвращает нулевое значение.
`RejectTransfer(input,errorCode)`
  Эта функция отвергает запрос StartTransfer.
  Значение параметра input должно Событием StartTransfer, которое необходимо отвергнуть.
  Значение параметра errorCode должно быть строкой.
  Функция StartTransfer в Задаче, которая отправила Событие StartTransfer, выходит из состояния ожидания и возвращает строку с кодом ошибки.
`AcceptTransfer(input)`
  Эта функция соединяет участника текущей Задачи с участником Задачи, отправившей Событие StartTransfer.
  Значением параметра input должно быть Событие StartTransfer, которое необходимо принять.
  Эта функция возвращает нулевое значение, если участники были успешно соединены. В противном случае, функция возвращает строку с кодом ошибки.
  Функция StartTransfer в Задаче, которая отправила Событие StartTransfer, выходит из состояния ожидания. Та функция возвращает нулевое значение, если участники были соединены; в противном случае возвращается строка с кодом ошибки.

Если участники были соединены, то обе Задачи остаются в режиме `connected`, за исключением ситуации, когда их участники явно отправили Сигналы на отсоединение. Задачи должны либо выйти, либо использовать процедуру `Disconnect` для полного отсоединения от своих участников.

### Запросы INFO

Приложения могут отправлять и получать запросы INFO.

Определённые INFO запросы (такие, как запросы с событиями DTMF) обрабатываются автоматически и не имеют отношения к настоящему разделу.

Данные INFO запросов представлены в виде словаря, в котором содержатся следующие элементы:

`Content-Type`
  Этот обязательный элемент с типом строка содержит Content-Type тела запроса (такое, например, как `application`).
`Content-Subtype`
  Этот опциональный элемент с типом строка содержит подтип Content-Type тела запроса.
`""` (пустой ключ)
  Этот опциональный элемент с типом строка содержит содержимое тела запроса.

`SendCallInfo(params)`
  Эта функция посылает участнику Задачи запрос INFO. Задача должна находиться в режиме `connected`.
  Значение params должно быть словарём, в котором содержатся данные запроса INFO.
  Если операция заканчивается неудачно, то функция возвращает строку с кодом ошибки.
  Если операция заканчивается успешно, то функция возвращает нулевое значение.

При отправке Задаче запроса INFO, Задача получает специальное Событие CallInfo. В элементе `parameter` События содержится словарь - данные запроса INFO.

`IsCallInfoEvent(input)`
  Эта функция возвращает истину, если значением input является Событие CallInfo. В противном случае функция возвращает нулевое значение.

### Служебные Запросы

`SendCallOptions(params)`
  Эта функция посылает участнику Задачи запрос OPTIONS (если диалог был установлен и Задача находилась в режиме `connected`) или произвольному коиенту (если Задача находится в режиме disconnected).
  Значение params интерпретируется аналогично значению destination в `StartCall`.
  Если операция заканчивается неудачно, то функция возвращает строку с кодом ошибки.
  Если операция заканчивается успешно, то функция возвращает нулевое значение.

## Поддерживаемые Форматы Медиа

Поддерживаются следующие форматы аудио файлов:

`WAV` (данные начинаются с тэга `RIFF`)
  файл должен содержать один кусок (chunk) `данных` с 8- или 16- битными данными PCM.
`au` (данные начинаются с тэга `.snd`)
  файл должен содержать либо 8- или 16- битные данные PCM, либо 8-битные данные mu-Law.

Руководство CommuniGate® Pro. Copyright © 1998-2009, Stalker Software, Inc.