[asterisk-app-dev] ARI Channel-Exec Suggestion

Matthew Jordan mjordan at digium.com
Mon Feb 17 22:38:08 CST 2014


On Mon, Feb 17, 2014 at 4:34 AM, Alistair Cunningham
<acunningham at integrics.com> wrote:
> On 17/02/14 03:27, Matthew Jordan wrote:
>>
>> In general, I'm against the idea of having a mechanism to execute
>> dialplan applications through ARI.
>
>
> I worry that not allowing this will make it difficult, perhaps impossible,
> for those with large AGI applications to reap the benefits of ARI.
>
> In particular, those doing billing cannot risk losing the control of the
> call and having an important billing event such as a hangup or transfer
> going unnoticed (or noticed late). Passing control of the call from Stasis()
> to back extensions.conf seems to me to be high risk for this (though I hope
> I'm wrong). I, and I suspect others too, would much prefer to have Asterisk
> call Statis() as soon as it receives an incoming call, and then have the
> statis application keep control of the call throughout.

Thinking about the concept of transfers:

* Today, if a SIP transfer occurs, the channel is removed from the
currently executing AGI and transferred to the specified destination.
When that occurs, for all intents and purposes, it looks like the
channel has hung up and returned to the dialplan. The same is true for
Asterisk's feature transfers - if you Dial from an AGI and you allow
blind transfers, the blind transfer will not return the channel to the
AGI - it will return it to the dialplan. The act of transferring a
channel from an external process or an internal process is completely
dialplan dependent today.

* ARI has the same behaviour as AGI, with one key difference: right
now, there is no mechanism to use the features. Instead, you can
implement your own features by capturing the DTMF and choosing to take
some action. While you could release the channel back to the dialplan
- or send it to Park - you could just as easily create your own
'blind', 'attended', 'parking' - or virtually anything else. In this
regard, ARI has the same limitation as AGI - and externally initiated
transfer will trigger the same results - but is more flexible
internally. Note that you can always prevent externally initiated
transfers at the channel driver level, if you wish.

Also note that due to the new bridging core, things are far less
likely to randomly steal your channel and not tell you about it.
Channels have a well defined lifetime in bridges. When an externally
initiated transfer occurs, ARI now also receives additional
information about what just occurred via the BridgeBlindTransfer [1]
and BridgeAttendedTransfer [2] events.

[1] https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+REST+Data+Models#Asterisk12RESTDataModels-BridgeBlindTransfer

[2] https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+REST+Data+Models#Asterisk12RESTDataModels-BridgeAttendedTransfer

>> (1) It confuses AGI and ARI. AGI does it's job well: allow for remote
>> execution of the dialplan from an external source. Heck, you can even
>> use an AGI to exec a Stasis application to toss the channel over to
>> ARI - that direction is just fine.
>
> That appears to me to mean that those who need AGI features are stuck with
> AGI and cannot fully migrate to ARI. Maybe they can partially, but they're
> going to end up with a hybrid AGI/ARI application in the same way they have
> a hybrid AGI/AMI application now.
>

I think it all depends on what you're trying to do. Remember: the
stated goal of ARI was not to fully replace AGI/AMI. It may, for some
people - and who knows, it may get to that point. I'd certainly like
it to. But the goal is to allow someone to replace Queue or VoiceMail.

>> (2b) Remote execution of other dialplan applications opens up a whole
>> world of permission escalation vulnerabilities. For example, would it
>> be allowable for me to run the System dialplan application through
>> that exec statement?
>
> Don't we already allow that in AGI?

Yes, I'm not sure it's such a good idea. :-)

AGI "gets away" with this by not having any permissions - it's hard to
have a permission escalation vulnerability when there are no
permissions! ARI has authentication with some very coarse grained
permissions (read/write). Since we authenticate and provide
permissions, it by its very nature opens us up to possible permission
escalation vulnerabilities. I don't think that's a bad thing, but it
is something to keep in mind. I do feel like we avoided the worst of
AMI's flaws by not implementing nearly arbitrary authorization levels
that don't have a logical mapping in the core - but it's worth keeping
in mind that the dialplan is powerful. Asterisk is powerful. I'm not
sure we need system altering power exposed through an external facing
interface.

>
>> (3) As time goes on and more resources are added, the need for this
>> functionality will diminish. Right now, channel technology agnostic
>> text messaging, i.e., MessageSend, speech recognition, and text to
>> speech are some of the more obvious candidates for resources; however,
>> I think we've already hit that "90% of the dialplan functionality is
>> doable through ARI" point. As we continue to find and build the things
>> that people need, I think the desire for this feature will be less -
>> other than some people will always like the dialplan :-)
>
>
> I agree that this is the long-term answer. Here are the Asterisk
> applications Enswitch does an AGI EXEC on:
>
> AGI(), because we support AGI user plugins.
> AMD()

AMD is a weird one. There's a category of modules written for Asterisk
that do media stream analysis that are hard to replicate in any
interface, and admittedly, this would be one. Right now, this would
have to be done outside of ARI.

> Answer()

POST /channels/{id}/answer

> Background()

As ARI is asynchronous, this always happens. POST /channels/{id}/play
and handle the DTMF events.

> Busy()

DELETE /channels/{id}?reason=busy

> ChanSpy()

POST /channels/{id}/snoop

> ConfBridge()

You can create your own conferences with your own business logic using
holding bridges, mixing bridges, and their respective operations.

> Congestion()

DELETE /channels/{id}?reason=congestion

> Dial()

Dial is a few steps:
(1) Originate a new channel using POST /channels
(2) When you get a ChannelStateChanged event for the originated
channel indicating that it is ringing. optionally POST
/channels/{caller}/ring (or play music, or do nothing)
(3) When you get a ChannelStateChanged event for the originated
channel indicating that it answered, POST /bridges, then add the
channels to the newly created bridge.

Or don't put them in a bridge - you can do whatever you want with them.

> Echo()

You could probably create Echo in a perverse fashion using some
convoluted bridges and Local channels, but otherwise, currently there
is no way to create an Echo loop on a channel. (How useful is this
really - or is a channel getting put into Echo merely to hold it
forever?)

> Hangup()

DELETE /channels/{id}

> Monitor()

(1) Issue a POST /channels/{id}/snoop
(2) Take the newly created snoop channel and issue a POST
/channels/{id}/record on it

> MusicOnHold()

Issue a POST /channels/{id}/moh

> Page()

(1) Issue a *lot* of POST /channels
(2) For each posted channel, issue a POST /channels/{id}/mute
(3) Create a bridge via POST /bridges. Put all channels in it.
(4) Put your announcer in the bridge and broadcast to the world.

> Playback()

POST /channels/{id}/play

> Playtones()

Not yet, but it'd be easy to add as a URI scheme to /play - and we
probably should.

> Progress()

Happens automatically if the channel isn't answered and a media
operation starts.

> ReceiveFax()

Nope!

> Record()

POST /channels/{id}/record

> Ringing()

POST /channels/{id}/ring

> SendFax()

Negatory.

> StartMusicOnHold()

POST /channels/{id}/moh

> StopMonitor()

For the channel that you created as a snooping channel; delete it.

> StopPlaytones()
> UserEvent()

No, but this is on the short list now that we have JSON bodies.

>
> Before we re-write our code to use ARI, we need to be confident that there's
> a way to implement (or elegantly work around) all of these. Many are no
> problem. Answer() is already implemented, for example. There are some that
> worry me though, such as AMD(), ReceiveFax(), and SendFax(). Of course
> checking all of them in detail is my job, but if you could quickly cast your
> eye down the list and see if there are any obvious problems it would be much
> appreciated.

So the three you that you called out are also the three that would be
the most problematic. But let's think about the use cases for these:

* SendFax/ReceiveFax are highly specialized for specific types of
calls. Once a call has been determined to be servicing a fax, it's
usually only going to get dropped into one of these two applications
and then the call doesn't do much else. There's little business logic
in these applications as well - other than knowing whether or not it
worked and doing something with the resulting fax, you basically just
want it to either send the image or receive it. Since the goal for ARI
is to allow people to implement business logic outside of Asterisk -
and these two applications by the nature of what they do eschew much
business logic in the first place - there's not a lot of value in
putting them in ARI, save to prevent someone from writing any
dialplan.

I wouldn't say that we would never put a /fax resource in ARI, but
that doesn't feel quite as important as some of the others.

* AMD - as I mentioned above, this one is odd. I'd put Zapateller in
there as well. I'd have to think about that one some more.

But think about it this way: out of all of the Asterisk applications
you listed, there's really only three that are not readily doable, and
all three of those are highly special purposed. Putting a call to AMD
in front of Stasis for outbound dialers or using the fax extension for
ReceiveFax is a small short term solution. And I think the flexibility
afforded by the other operations is still pretty worthwhile.

Matt

-- 
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



More information about the asterisk-app-dev mailing list