Asterisk Tutorial 56 — Asterisk AMI Configuration | by pascom | Medium

__construct(),__destruct() и $this->ini

Основная задача конструктора объявить все переменные которые будут использоваться в классе. Все переменные у нас будут храниться в массиве $this->ini.

Остальные переменные в данный массив мы будем добавлять по мере необходимости, и будем детально рассматривать каждый элемент по функциональности.

Access control lists

Access Control Lists can be used to filter connections based on address. If an attempt to connect from an unauthorized address is detected, the connection attempt will be rejected.

Accountcode

The channel’s accountcode.

Action

Action specifies the action to execute within Asterisk. Each value corresponds to a unique action to execute within Asterisk. The value of the Action field determines the allowed fields within the rest of the message. By convention, the first field in any action is the Action field.

Action responses

When an Action is submitted to AMI, the success or failure of the action is communicated in subsequent events.

Actionid

ActionId is a universal unique identifier that can optionally be provided with an action. If provided in an action, events that are related to that action will contain the same ActionId value, allowing a client to associate actions with events that were caused by that action.

It is recommended that clients always provide an ActionId for each action they submit.

Actions

The supported actions for Asterisk 12 are listed here:

Asterisk 12 AMI Actions

While new AMI Actions may be added over the lifetime of Asterisk 12, existing AMI Actions will not be removed.

Optional fields may be added to an existing AMI action with altering the AMI version number, but required fields will not be added or removed.

Asterisk tutorial 56 — asterisk ami configuration

Following on from last week’s introduction to the ‪Asterisk‬ AMI, here we are with part 2 on enabling and configuring your Asterisk IP PBX manager interface.

Basic channel lifetime

All channels begin with a Newchannel event. A Newchannel will always contain the following fields:

Changes in the state of the channel, i.e., the ChannelState field, are conveyed via Newstate events.

Notification of a Channel being disposed of occurs via a Hangup event. A Hangup signals the termination of the channel associated with the Uniqueid. After the Hangup event, no further events will be raised in relation to the channel with that Uniqueid, and the communication between the endpoint and Asterisk via that channel is terminated.

Bridgecreator

Some bridges are created as the result of a particular application or action. If so, the bridge will specify who created it. If the bridge was not created as a result of any particular application or action, the field will have the value <unknown>.

Bridgename

Some bridges are created with a names as a result of their application. If so, the bridge will specify the name given to it. If the bridge was created without a name, the field will have the value <unknown>.

Bridgenumchannels

The number of channels currently in the bridge.

Bridgetechnology

How the media can be mixed within a bridge. Specific modules in Asterisk provide different bridge technologies that can be used by Asterisk to alter how media passes between the participants. For a given bridge, the BridgeTechnology* can also change as the number and type of participants change. The most common bridge technologies are:

  • holding_bridge – normal participants joining the bridge may receive audio, but audio sent from a normal participant is dropped. Special participants, known as announcers, may broadcast their audio to all normal participants.

  • native_dahdi – a native bridge between DAHDI channels. Media is passed directly between all participants.

  • native_rtp – a native bridge between channels that use RTP for media. Media is passed directly between all participants.

  • simple_bridge – a two-party bridge between any two channels. Media is passed through the Asterisk core between the two participants.

  • softmix – a multi-party bridge between one or more participants. All media from all participants is mixed together and sent to all participants.

Bridgetype

The type of the bridge. Bridge types determine how a participant in a bridge can behave. For example, a ‘base’ bridge is a bridge that has few inherent properties or features associated with it, while a ‘parking’ bridge is one used for a parking application. Specific modules within Asterisk will determine the type of bridge that is created.

Note that this is not the same as how media within a bridge is mixed. How media is mixed between participants in a bridge is determined by the BridgeTechnology.

Bridgeuniqueid

A unique identifier for the bridge, which provides a handle to actions that manipulate bridges.

Bridging

A bridge contains 0 or more channels. When a channel is in a bridge, it has the potential to communicate with other channels within the bridge. Before channels enter a bridge, a BridgeCreate event is sent, indicating that a bridge has been created.

Calleridname

The current caller ID name. If the caller ID name is not known, the string “<unknown>” is returned instead.

Calleridnum

The current caller ID number. If the caller ID number is not known, the string “<unknown>” is returned instead.

Channel

The current Asterisk channel name. This corresponds to the Channel field in actions.

Channel variables

For each channel variable that is changed, a VarSet event is sent to the client. The VarSet event contains the new value of the appropriate channel variable. Note that channel variables can also be conveyed in ChanVariable fields.

Channels

This section lists fields that apply generally to all events that occur due to interactions upon an Asterisk channel.

Events that relate multiple channels will prefix these fields with an event specific role specifier. For example, a DialBegin or a DialEnd event will prefix the outbound channel’s fields with Dest. So, the Channel field is the DestChannel field; the Uniqueid field is the DestUniqueid field, etc.

Channelstate

The current state of the channel, represented as an integer value. The valid values are:

Похожее:  Открытие кейсов Standoff 2 — StaddyDrop.one

Channelstatedesc

The text description of the channel state. This will be one of the State descriptions in the table in ChannelState.

Chanvariable

Channel variables specific to a channel can be conveyed in each AMI event related to that channel. When this occurs, each variable is referenced in a ChanVariable field. The value of a ChanVariable field will always be of the form key=value, where key is the name of the channel variable and value is its value.

Connect() и disconnect()


Для соединения с сокетом я решил использовать функцию fsockopen.

fsockopen(host, port,$a,$b,$c);
где
host - IP адрес хотса к которому мы будем соединяться,
port - порт сервера на который будет идти соединение,
$a - номер ошибки в случае неудачного соединения,
$b - текстовое описание ошибки в случае неудачного соединения,
$c - таймаут сокета(очень интересный параметр, но вообще не работающий параметр).

Из описания функции мы можем понять, что нам нужно ввести как минимум 2 переменные в глобальный массив. Это IP адрес сервера и порт для коннекта. Так как $a,$b возвращаемые значения (а мы не справочное бюро чтобы хранить справки) то их мы проигнорируем. А $c параметр вообще не работает, поэтому держать его в памяти не будем.

Почему я пишу что не работает? Потому что это реальный опыт работы данной функции в демонах, которым глубоко побарабану на собственные же спецификации PHP.

Для двух новых переменных введем 2 элемента массива:

$this->ini["host"] = "127.0.0.1";       /* IP сервера */
$this->ini["port"] = "5038";              /* Порт для соединения */

Напишем функцию:

Connectedlinename

The current connected line name. If the connected line name is not known, the string “<unknown>” is returned instead.

Connectedlinenum

The current connected line number. If the connected line number is not known, the string “<unknown>” is returned instead.

Context

The current context in the dialplan that the channel is executing in.

Dialing and origination

Dial operations always result in two events: a DialBegin event that signals the beginning of the dial to a particular destination, and a DialEnd event that signals the end of the dialing. In parallel dialing situations, DialBegin/DialEnd events MUST be sent for each channel dialed. For each DialBegin event sent, there MUST be a corresponding DialEnd event.

Dialplan execution

As a channel executes operations in the dialplan, those operations are conveyed via a NewExten event. Each transition to a new combination of context, extension, and priority will trigger a NewExten event.

Enabling the asterisk ami

The Asterisk AMI is disabled per default due to the security risks enabling can open your system to. In order to check which ports are open, you can use the command

netstat - lpn

This will provide you a list of ports which are open such as those used for SIP, AJAX and so on. To enable the Asterisk AMI, simply edit the manger.conf:

/etc/asterisk/manager.conf

Scroll down to the security notice which warns you to neverenable the Asterisk AMI on a public IP address without security protocols in place. Asterisk themselves recommend using SSL connections or VPN tunnels if you wish to use Asterisk AMI through the internet.

Event

The unique name of the event being raised. The value of the Event field determines the rest of the contents of the message. By convention, the Event field is the first field in an AMI message.

Eventlist

Some actions will cause a chain of events to be created. Events that are a response to an action that causes such a sequence will contain the EventList field with a value of “start”. When all generated events have been sent, a final event will be sent containing the EventList field with the value “complete”.

If, for some reason, an error occurs and the events cannot be sent, an event will be sent with an EventList field that contains the value “cancelled”.

Note that the events that mark the completion or cancellation of an event list are not technically action responses, and have their own specific event types.

Events

The supported events for Asterisk 12 are listed here:

Asterisk 12 AMI Events

While new AMI Events may be added over the lifetime of Asterisk 12, existing AMI Events will not be removed.

Fields may be added to an existing AMI event without altering the AMI version number, but existing fields will not be removed.

Exten

The current extension in the dialplan that the channel is executing in.

General fields

This section lists fields that apply generally to all actions.

Getting started with the asterisk ami

Before starting with configuring your Asterisk Manager Interface, it is important to understand the security issues surrounding enabling the Asterisk AMI and precautions that you should take.

Therefore, if you have not already done so, please refer to our theoretical intro to the AMI in the last tutorial.

Upgrade your business communications with a free pascom Cloud phone system today

Masquerades

This section only exists to explicitly call out the fact that Masquerades are gone.

Message

An optional text message that provides additional contextual information regarding the success or failure of the action.

Message layout

AMI is an ASCII protocol that provides bidirectional communication with clients. An AMI message – action or event – is composed of fields delineated by the ‘rn’ characters. Within a message, each field is a key value pair delineated by a ‘:’. A single space MUST follow the ‘:’ and precede the value.

Actions are specified in a similar manner. Note that depending on the message, some keys can be repeated.

In addition, no ordering is implied on message specific keys. Hence, the following two messages are semantically the same.

This is also true for events, although by convention, the Event key is the first key in the event. If an action or event contains duplicate keys, such as Variable, the order in which Asterisk processes said keys is the order in which they occur within the action or event.

Похожее:  Authentication using Python requests - GeeksforGeeks

Keys are case insensitive. Hence, the following keys are equivalent:

The case sensitivity for values is left up to the context in which they are interpreted.

More info

pascom are the developers of the enterprise grade pascom VoIP phone system software. As an open standards IP PBX, pascom systems offer a cost effective alternative to proprietary solutions and provides businesses with a fully featured Unified Communications solution to boost productivity, increase mobility and reduce costs.

For more on our pascom phone system or to arrange a personalised demo, give us a call on 49 991 29691 200. Alternatively, contact us via our website or take our pascom phone system for a test drive with our Free Edition and discover first hand how your business can benefit.Until next time — Happy VoIPing!

Priority

The current priority of the current context, extension in the dialplan that the channel is executing in.

Privilege

The class authorizations associated with this particular event. The class authorizations for a particular event are in a comma-delineated list. For more information, see class authorizations.

Protocol overview

Asterisk provides a number of interfaces that serve different purposes. Say, for example, we wanted to manipulate a call between Alice and Bob via some external mechanism. Depending on what we wanted to do with the call, we may use one or more interfaces to manipulate the channels that make up the call between Alice and Bob.

In general, AMI is used to manage Asterisk and its channels. It does not determine what actions are executed on a particular channel – the dialplan and/or an AGI interface does that – but it does allow a client to control call generation, aspects of call flow, and other internals of Asterisk.

At its heart, AMI is an asynchronous message bus: it spills events that contain information about the Asterisk system over some transport. In response, clients may request that Asterisk takes some action. These two concepts – actions and events – make up the core of what is AMI.

As AMI is asynchronous, as events occur in Asterisk they are immediately sent to the clients. This means that actions issued by entities happen without any synchronization with the events being received, even if those events occur in response to an action. It is the responsibility of entities to associate event responses back to actions.

Clients wishing to use AMI act as clients and connect to Asterisk’s AMI server over a supported transport mechanism. Authentication may or may not be enabled, depending on the configuration. Once connected, events can be automatically spilled to the connected clients, or limited in a variety of fashions.

More information on the various ways a client can be configured can be seen in AMI Configuration.

Historically, AMI has existed in Asterisk as its own core component manager. AMI events were raised throughout Asterisk encoded in an AMI specific format, and AMI actions were processed and passed to the functions that implemented the logic.

In Asterisk 12, AMI has been refactored to sit on top of Stasis, a generic, protocol independent message bus internal to Asterisk. From the perspective of clients wishing to communicate with Asterisk over AMI very little has changed; internally, the Stasis representation affords a much higher degree of flexibility with how messages move through Asterisk. It also provides a degree of uniformity for information that is propagated to interested parties.

Response

Contains whether or not the action succeeded or failed. Valid values are “Success” or “Error”. Events that are in response to an action MUST include this field.

Setting ami permissions

Before moving forward, it is important to understand that the Asterisk AMI has two types of permissions; read and write. These are the applied to a number of classes as shown below. It is also important to note that if you do not allow permissions to a class then it is automatically denied.

Sleepi();

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

class Asterisk_ami
{

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    function __construct ()
    {
        /* Настройки класса по умолчанию */
        $this->ini["con"] = false;              /* ссылка на соединение */
        $this->ini["host"] = "127.0.0.1";       /* IP сервера */
        $this->ini["port"] = "5038";            /* Порт для соединения */
        $this->ini["sleep_time"]=1500;          /* В демонах эта цифра намного меньше, в моем тестовом сервере, всего "5" */
    }


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /*  Задает стандартную паузу между функциями записи и чтения    */
    function sleepi ()
    {
        sleep($this->ini["sleep_time"]);        /* Скрипт будет засыпать на заданное время */
    }
}

Transfers

Transfer information is conveyed with either a BlindTransfer or AttendedTransfer event, which indicates information about the transfer that took place. BridgeLeave/BridgeEnter events are used to indicate which channels are talking in which bridges at different stages during the transfer.

Transfers do a Lot

Icon

Depending on the type of transfer and the actions taken, channels will move in and out of a lot of bridges. The purpose of the two transfer events is to convey to the AMI client the overall completed status of the transfer after the users have completed their actions. With Blind Transfers, this typically happens very quickly: Asterisk simply has to determine that the destination of the transfer is a valid extension in the dialplan.

Attended transfers, on the other hand, can involve a lot more steps. Parties can consult, toggle back and forth between consultations, and merge bridges together. Channels can be transferred to a dialplan application directly, and not to another party! As such, Asterisk will send the AttendedTransfer event when it knows whether or not the Attended Transfer has completed successfully, and will attempt to convey as much information as possible about the final status of the transfer.

Похожее:  TLauncher org регистрация: как создать аккаунт, вход в личный кабинет

For more information on these events, see BlindTransfer and AttendedTransfer.

Transports

AMI supports the following transport mechanisms:

Two party bridging

Parties are bridged by virtue of them entering a bridge, as indicated by a BridgeEnter. When parties are no longer talking, a BridgeLeave event is sent for each channel that leaves the bridge.

Uniqueid

A universal unique identifier for the channel. In systems with multiple Asterisk instances, this field can be used to construct a globally unique identifier for a channel, as a channel name may occur multiple times across Asterisk instances.

Write();

Для работы с Астериск АМИ мы должны записывать в сокет пакеты строк, в ответ на которые мы будем также получать строки о статусе наших запросов. Для записи мы будем использовать php функцию fwrite.При этом в с каждым пакетом мы можем отправить индикатор ActionID нашего запроса, чтобы получив пакеты информации от Астериска мы могли классифицировать это пакеты по отправленным заранее событиям.

    /* Функция для записи в сокет */
    function write($a)      /* $a это строка которую мы должны записать в сокет */
    {
        $m = rand (10000000000000000,99999999900000000);        /* Рандомое число, для генерации рандомного ActionID */
        fwrite($this->con, "ActionID: $this->action_id$mrn$arnrn"); /* Записываем в сокет */
        $this->sleepi();        /* Суть этой фунции я расскажу в следующем параграфе. */
        return $m;     /* Возвращаем ActionID */
    }

Вместо предисловия

Приветствую сообщество!

Моя первая статья Пример реализации обращения к Asterisk CLI на PHP. Структуризация ответа звездочки наконец то перешла из модерации в песочницу и модератор сразу дал мне полные права для публикации на хабре.

Я хочу начать цикл статей о том как можно реализовать собственное API для обращения с Астериском через AMI. Если у Вас имеются время, желание и самое главное опыт, поддержать меня и попытаться составить команду которая на данном портале создаст полноценное php API для взаимодействия с AMI Астериска велком к диалогу.

Задача очень интересная так как многие сервисы посвященные Звездочке сразу прячут всю информацию о попытках разработки собственных интерфейсов для Asterisk. Хотя мой опыт который я здесь изложу может стать для многих «коддеров» попыткой потешить свое «эго», но вариантов создать собственное веб приложение, которое не будет глючить каждую секунду не даст (правда если вы виртуоз языка javascript то очень даже получится какой нибудь грамотный заменитель буржуйской веб-морды для астера).

В этой части я покажу что написать собственный класс для обращения к AMI звездочки проще простого, главное идти от простого к сложному.

Для особо ленивых в конце статьи готовый (рабочий) модуль с классом Asterisk AMI. С примерами запросов. Класс полностью рабочий и готов к использованию.

Матчасть

Я решил реализовать механизм работы сокета на fsockopen.

Прежде чем начать коддинг маленький ликбез.

Функции и ключевые слова php встречающиеся в коде

.

* Пояснения составлены лично мной, не являются энциклопедическими данными или стандартами, и служат лишь для пояснения кода на данной странице. Если Вас не устраивает мое описание просьба отписаться в комментах. В случае если Ваше описание будет более ясно описывать приведенные выше понятия для объяснения кода примеров,то я внесу в статью изменения. Корректировки будут указаны с Вашим авторством.

Настройка asterisk ami

Asterisk Managment Interface (AMI) — мощный интерфейс API для Asterisk, позволяет управлять, выполнять команды, получать уведомления о событиях в реальном времени и т.д.

Для включения Asterisk AMI откроем файл /etc/asterisk/manager.conf в текстовом редакторе и укажем параметры:

Теперь создадим файл настроек для первого пользователя:

И добавим в него:

[admin]
secret = IXNFO
deny = 0.0.0.0/0.0.0.0
permit = 127.0.0.1/255.255.255.0
permit = 192.168.2.2/255.255.255.255
permit = 192.168.5.5/255.255.255.255
read = system,call,log,verbose,command,agent,user,config,dtmf,reporting,cdr,dialplan,originate
write = system,call,log,verbose,command,agent,user,config,dtmf,reporting,cdr,dialplan,originate

Где я указал:
admin (логин пользователя)
secret (пароль пользователя)
deny (запрещаем всем доступ)
permit (разрешаем доступ только с указанных IP адресов и сетей)
read и write (определяем права пользователю, я указал все)

Применим изменения:

Убедимся что Asterisk AMI запущен:

Пример просмотра доступных команд, настроек, пользователей, подключенных пользователей, событий:

Включить и отключить режим отладки можно так:

Смотрите также мои статьи:
IPTables правила для Asterisk AMI
Прочие статьи статьи о Asterisk

Определение обязательного функционала класса


Составим таблицу, чтобы понять какой функционал необходимо добавлять в класс.

Это грубое ТЗ которое позволит написать класс для взаимодействия через PHP с Asterisk AMI.

Регламент написания кода в классе для внесения ясности при его чтении.

При написании данного класса я использовал следующий регламент:

  • $i, $ii,$iii,$iiii — все начинающиеся с $i переменные являются переменными цикла for
  • $s, $ss, $sss, $ssss — все начинающиеся с $s переменные являются строками
  • $m, $mm, $mmm, $mmmm — все начинающиеся с $m переменные являются массивами
  • Каждый уровень вложенности кода отступает от родительского на четыре пробела.
  • Каждая переменная объявленная в функции и не являющейся глобальной, обязательно требует прямого уничтожения функцией unset для того чтобы демоны на PHP не кушали память.

Резюме


Создать собственный класс для работы с сокетами в асинхронном режиме не сложно. И не важно, будет ли это работа с Астериск АМИ или другим серверным приложением.

Отдельное спасибо HiNeX за ошибки найденные в промежуточном коде.

Изменил готовый класс в связи с рекомендациями AotD и RUgaleFF.

Спасибо всем кто дочитал. И до встречи на порталах ТМ.

(Если вы считаете что стоит продолжить, то какой из функционалов Астериск АМИ вы хотите, чтобы я показал в следующей части? Пишите в комментариях.)

Убедительная просьба для тех кто минусует статью, если Вам не трудно, пожалуйста, напишите причину.

Init() и read();


Здесь все просто. Смотрим код.

    /*  Считывает данные из сокета  */
    function read()
    {
        $mm = array();
        $b = array();
        $k = 0;
        $s = "";
        $this->sleepi();
        do
        {
            $s.= fread($this->con,1024);
            sleep($this->read_sleep_time);
            $mmm=socket_get_status($this->con);
        }   while ($mmm['unread_bytes']);
        $mm = explode ("rn",$s);
        for ($i=0;$i<count($mm);$i  )
        {
            if ($mm[$i]=="")
            {
                $k  ;
            }
            $m = explode(":",$mm[$i]);
            if (isset($m[1]))
            {
                $this->ini["lastRead"][$k][trim($m[0])] = trim($m[1]);
            }
        }
        return $this->ini["lastRead"];
    }

В итоге мы получили класс для работы с Астериск AMI:

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector