[asterisk-dev] ARI Extending Existing Feature: bridge control

Matthew Jordan mjordan at digium.com
Thu Dec 18 12:38:42 CST 2014

On Thu, Dec 18, 2014 at 10:31 AM, Leif Madsen <lmadsen at thinkingphones.com>
> On 18 December 2014 at 11:07, Paul Belanger <paul.belanger at polybeacon.com>
> wrote:
>> On Thu, Dec 18, 2014 at 1:59 AM, Nir Simionovich
>> <nir.simionovich at gmail.com> wrote:
>> > New question: Do we want to enable legacy features inside ARI?
>> >
>> New answer: I don't believe so.
>> I think this issue / question is the hardest thing to understand about
>> ARI.  There really isn't any sort of link to existing Asterisk
>> application or features; not yet any ways.  Somebody has to build it
>> again a top of ARI.
>> When I first dreamed of using ARI I was looking at it from a
>> configuration management tool mindset.  Oh, I could create a new peer
>> in chan_sip over HTTP or let me reconfigure features.conf using ARI.
>> However, as I started playing with it more I found that was not what
>> it did.  And, changing it to do something like that doesn't feel like
>> the right approach.
>> Now, that being said. Creating some sort of interface to control
>> sorcery objects, now that would be cool.  Having sorcery connect to
>> redis and change key / values directly in redis for sip peers would be
>> hotness.  However, I'm not sure I would want to have Asterisk serve up
>> that interface directly.  Feels more like an external application
>> would serve up the REST interface into redis, allowing the user to
>> change key/pairs.
>> I also believe, until there are some standard ARI libraries /
>> application (for example app_dial replacement). It will feel like a
>> large task to build anything in ARI, because some of the core
>> application basically need to be written from scratch.  And I think
>> this is the main reason people are slow to move to ARI or fearful from
>> dropping the dialplan.  Because doing:
>> exten => s,1,NoOp()
>>     same => n,Dial(SIP/foo at example.org)
>> is a lot easier then origination a channel over ARI, creating bridges
>> and playing any tones needed using ARI.  Easier might not be the right
>> work, more steps required is.
> I also agree that we do not want to start making ARI start talking to
> applications.
> As discussed at AstriDevCon, the push is really to start making Asterisk a
> media communications platform. The way to do that is to move away from the
> dialplan centric driven applications and to move to a decentralized model
> applications and business logic being separated from Asterisk, and
> essentially making Asterisk much dumber in terms of the actual business
> logic and routing logic, and making it a lean mean media communications
> machine. The way forward sometimes is to stop looking back.
> Currently both AMI and AGI are still happily co-existant in Asterisk, and
> should be considered the defacto interface to traditional methods of
> Asterisk business logic (dialplan, etc). When flipping to ARI, it is a
> different mind set that does take some time to get around. Much like Paul
> had my own preconceived notions about what ARI was and was initially
> disappointed it didn't match what I thought it should have been. However
> over the last few months of watching what Paul has been doing along with
> some small side POC stuff to better understand what ARI is intended for,
> definitely has become a lot clearer.
> At the most basic levels, ARI to me is a bridge control interface that
> allows you to hook channels together while not worrying about transcoding,
> media characteristics etc. You have two or more channels that may or may
> speak the same language, and your external applications stick them
> and Asterisk acts as the universal translator for those channels. By
> all your business logic and controls outside of Asterisk, it makes the API
> much simpler to interoperate with, and allows great scaling possibilities.
> Admittedly I'm still a bit naive on a lot of the ARI front, but one thing
> gut tells me, is it is a new interface, and should not be confused as a
> replacement to the legacy (term used loosely) methods of building Asterisk
> systems. This is one of those situations that I feel avoiding legacy and
> backwards compatibility with the traditional methods is going to really
> up a better realm of possibilities with ARI. If someone truly just needs
> HTTP based interface for controlling dialplan and such, I feel a
> application (library) should just be written for AMI and AGI that permits
> that and has that goal. Overloading what ARI is supposed to be doing is a
> step backwards in my opinion.

Exposing Asterisk features (and that term encompasses 'features.conf'
features as well as other things) in the short run would add more features
to the API, but in the long run will result in severely limiting the ARI
API - and making it really difficult to build ARI applications. I think
everyone is on this page from this thread, but for the sake of posterity,
I'll go into some of where this would fall apart if we tried to put
'features' into ARI.

Integral to ARI is the concept of control. When a channel is in your Stasis
dialplan application, *you* own the channel. Asterisk has handed it over to
your external application to control. When a channel is not in a Stasis
application, your ARI application can be aware of the channel's existence,
but it does *not* own the channel - Asterisk does. And Asterisk will do
crazy complicated things to channels when it owns them (re: masquerades,
media manipulations, lots of swapping between bridges, local channel
optimizations, etc.) These operations are safe when Asterisk manipulates
them, but cannot be made safe to all ARI operations - initiating a /play
operation on a channel in the middle of an existing media operation would
be "interesting". Taking a Local channel that is half-way through an
optimization and pushing it into a bridge would be a "bad thing". This hard
distinction is what makes ARI safe: because we *know* that a channel in
Stasis is owned by an external application, we can make assumptions about
what Asterisk can and cannot do to the channel. The reverse is also true:
when Asterisk controls a channel, we can make assumptions about what the
ARI API will let an external application do to a channel.

Having a safe border makes both worlds happier. "Good fences make good

So, let's see where this breaks down with features. Say I wanted to have
Asterisk features attended transfers in ARI. I'd want some 'flag' passed in
when I add a channel to a bridge that says "yes, this channel can perform
an attended transfer". Maybe something like this:

POST /bridges/bridge-12345/addChannel?channel=channel-1&feature=atxfer

Er... except, how does Asterisk know what DTMF sequence triggers the
attended transfer feature? I could rely on features.conf, but that's a poor
solution that falls afoul of scalability and multi-tenancy. I could just
require people to use FEATURE_MAP on the channel prior to adding it to the
bridge, which isn't too bad.

POST /channels/channel-1/variable?variable=FEATURE_MAP(atxfer)&value=1
POST /bridges/bridge-12345/addChannel?channel=channel-1&feature=atxfer

Okay, so that's not so bad. Yay! I have attended transfers! Let's see where
this starts to break down:

My ARI application controls bridge-12345 and added channel-1 to it. Let's
say my ARI application also had a channel-2 that was added to the bridge:

POST /bridges/bridge-12345/addChannel?channel=channel-2

So channel-1 initially talks to channel-2, and then decides to perform a
features attended transfer of channel-2 to someone else. When channel-1
hits '1' and starts the features attended transfer code, channel-1 will get
placed into a bridge created by Asterisk and a Local channel will be
created to go execute the dialplan extension that they enter. The bridge
and Local channel created as part of this is not controlled by my ARI
application; nor is the resulting execution of the dialplan at that
location: the core features code in Asterisk is working with the dialplan,
and goes to execute dialplan at that location.

Let's assume that the dialplan location that is the target of the attended
transfer performs a Dial operation, creating an outbound channel we'll call
channel-3. channel-3 is Answered, and a new bridge is formed between the
Local channel that executed dialplan and channel-3. Again, this is not
under the control of my ARI application; all of these channels are
controlled by Asterisk. Through Local channel optimization, channel-1 and
channel-3 will end up in the same bridge - neither of which is controlled
by ARI.

To recap:
 * We have had a Local channel be created and destroyed (via optimization)
that was not part of my ARI application
 * We have a new channel, channel-3, that is now talking to channel-1 - but
that I have no control over
 * We have an existing channel, channel-1, which ostensibly has now left my
application but is the channel I used to control
 * We have had two bridges be created that I had no control over, one of
which is now destroyed

All of which my ARI application however would generally want to be aware of
- as I still have channel-2 waiting in my ARI application bridge that I may
need to do something with.

Now things get really difficult to track and understand in the ARI
(1) If the attended transfer completes successfully, then either channel-2
will be moved into channel-3's bridge (that I don't control), or channel-3
will be moved into channel-2's bridge (that I do control). In this
particular case, channel-3 comes in "through the back door" into the ARI
application, while in the other case, channel-2 will leave "through the
back door" (this does work after some recent bug fixing). Regardless, there
are cases where an ARI application will have to understand that it will get
channels handed to it that it didn't expect, and cases where channels will
leave its application that it didn't expect.
(2) If channel-1 toggles between channel-2 and channel-3's bridges, there
will be race conditions in the controlling of channel-1: when it is in the
bridge with channel-2, ARI can control it; when it enters the bridge it
shares with channel-3, ARI can't control it. Since a human being is mashing
these buttons, you will have races where ARI thinks it can control
channel-1, but by the time the request reaches Asterisk, Asterisk will have
already moved it into a bridge with channel-3 and the request will fail.
(3) If the attended transfer is converged into a 3-way, then we'll have the
same situation as (1) but now with more channels. Again, we may lose
control of channel-2, while at the same time re-gaining control of
channel-1 and gaining control of channel-3.

None of this sounds easy for an ARI application to keep track of. The
answer here is *not* to allow ARI control things that Asterisk is
controlling: the number of race conditions, unsafe behaviours, and crashes
that would encounter is mind-boggling. I really can't predict how poorly
that would go, other than to say I would not want to try and maintain
Asterisk any longer :-)

There's a reason the only thing you can really do that truly alters the
state of a channel in AMI is Redirect - and that's not a trivial operation
to get right all the time internally.

What's more, what if I didn't want Asterisk's attended transfer behaviour?
What if I wanted channel-1 to only be able to perform attended transfers to
their supervisor - a much more likely scenario for call centers. This would
be nice, as for my application, I could bypass the need for the initiator
to 'dial an extension' - they could just hit 1 and have the whole process
kick off! Doing this would be extremely non-trivial in Asterisk, and nearly
impossible to do in a generic fashion. However, this is not especially
difficult to implement in JavaScript, Python, or any other language that
ARI lends itself to.

The point of all this is: Asterisk limits you. When you rely on its
internal mechanisms and constructs, yes, you don't have to write any code -
but you can only tweak it as far as it lets you go. ARI presents the
building blocks of Asterisk and lets you go build whatever you want with
it. While you can mix the worlds to an extent using the Stasis dialplan
application - which is a good thing - mixing the world owned by Stasis and
the world owned by the Asterisk core is fraught with peril: both for
Asterisk developers and for those attempting to build applications with ARI.


Matthew Jordan
Digium, Inc. | Engineering Manager
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA
Check us out at: http://digium.com & http://asterisk.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-dev/attachments/20141218/df43f4eb/attachment-0001.html>

More information about the asterisk-dev mailing list