Re: WebSocket Stasis Control Best Practice

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 






On Mon, Jun 16, 2014 at 7:42 AM, Ben Merrills <b.merrills@xxxxxxxxxxxxxxxx> wrote:
We had a similar discussion a while back about executing dialplan applications from within ARI. Please see: http://lists.digium.com/pipermail/asterisk-app-dev/2014-February/000367.html

Although this doesn't provide you with an answer, it may help you to understand the current thinking of the asterisk/ari development team


I'm going to chime in again on this topic, because I do think that this is one of the hardest points to grasp with the new interface.

To begin, it's important to understand how dialplan execution works within Asterisk. When a channel is executing dialplan, a dedicated thread - the pbx_thread - "owns" the channel. It is responsible for a variety of things: understanding the location of the channel in the dialplan stack, servicing frames from the channel in a timely fashion, running each application, and more. The pbx_thread is the thread that services the channel.

With AGI, you are performing remote execution of dialplan. Hence, executing any dialplan application from your AGI is completely within the scope of that interface. The pbx_thread is still the owner in this case - it just happens to be waiting for your command from the AGI. When it gets said command, it goes off and executes the dialplan just as if it were walking through statements in extensions.conf. There's a key point here however - while it is off executing dialplan, your AGI can't do anything with the channel. It doesn't own the channel - it merely gets to instruct the pbx_thread what to go do. If, for example, you sent said channel off into VoiceMail and then decided you wanted instead to Playback howler monkeys to the channel, you couldn't do that: the pbx_thread is off on its mission, and can't be interrupted.

With AMI, you don't really own channels - nor can you do much with them. There's really only two operations that affect the state of a channel - Redirect and Bridge. In the case of Redirect, you are "simply" moving a channel to a new location in the dialplan. Again, a pbx_thread still owns the channel - even when this occurs. With Bridge, you are doing something a bit more creative: both channels are stolen from their pbx_thread and shoved into a bridge. Now, of course, there is a slight problem - what happens when those channels leave the bridge? Unless AMI uses redirect on the channels from the bridge it created for them, there's no place for them to go - the threads that serviced them are long gone, and they don't have anywhere to return. They get hung up.

Contrasting both of these interfaces with ARI, there's two key differences:
(1) In AGI and AMI, you are constrained by the dialplan. This is not a terrible thing - dialplan is, after all, very powerful. But dialplan applications are an abstraction over Asterisk's core resources, and often they don't expose exactly what you want to do - or you have to do some strange machinations to get them to do what you want.
(2) AGI (in particular) and AMI (to a lesser extent) are channel based. While channels are still the most powerful construct in Asterisk, there are other resources - such as bridges and endpoints - that can also be manipulated - and typically are by dialplan applications.

ARI seeks an alternative path: get the channel out of the dialplan and hand it over to something external. Because we remove the dialplan from the equation, we can let something external asynchronously control the channel as well as bridges, endpoints, and other things.

As an example, take the Bridge AMI action and an equivalent operation in ARI.

When you execute Bridge in AMI in Asterisk 12, the following is what actually occurs:
(1) Create a new bridge.
(2) Find the first channel. If the channel is in a bridge, perform a bridge move operation. If the channel is not in a bridge, panic and do the following:
(2a) Issue an ast_channel_yank on the channel. This will (carefully) perform a masquerade: a new channel is created, the private data structure is taken from the existing channel and moved to the new channel, and the existing channel is hung up in a silent fashion. This is done to 'steal' the channel from the running pbx_thread.
(2b) Take the new channel - which we now own - and perform an ast_bridge_impart into the newly created bridge.
(3) Find the second channel. If the channel is in a bridge, perform a bridge move operation. If the channel is not in a bridge, panic again and do the following:
(3a) Issue an ast_channel_yank on the second channel. This will (again carefully) perform the dreaded masquerade: create a new channel, move the private data structure over, hang up the existing channel silently, and 'steal' the channel from the running pbx_thread.
(3b) Take the new channel - which again we now own - and perform an ast_bridge_impart into the newly created bridge.
(4) Return success

Consider, instead, adding two channels to a bridge in ARI:
(1) Make the bridge. This directly maps to ast_bridge_create.
(2) Add the first channel. Since ARI owns the channel, there is no need to yank it from something else. Call ast_bridge_impart.
(3) Add the second channel. Since ARI owns the channel, again, there is no need to yank it from somewhere else or perturb an existing thread. Call ast_bridge_impart.
(4) Rejoice in the lack of insanity.

If, on the other hand, ARI allowed a channel to be 'owned' by a dialplan application, we could not make the assumptions in steps 2 and 3 that ARI 'owns' the channel. We'd have to go through some severe machinations to get ownership again. And this is a relatively trivial case: manipulating media, for example, on a channel in a dialplan application has a lot of strange corner cases that could be extremely volatile.

Hence, the goal for ARI is not to turn it into dialplan execution. Instead, we want to find a way to enable use cases currently met by dialplan applications - typically in a fashion that provides information asynchronously to ARI applications. Hence, the TALK_DETECT function as a way to enable WaitForSilence/WaitForNoise.

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
_______________________________________________
asterisk-app-dev mailing list
asterisk-app-dev@xxxxxxxxxxxxxxxx
http://lists.digium.com/cgi-bin/mailman/listinfo/asterisk-app-dev

[Index of Archives]     [Asterisk SS7]     [Asterisk Announcements]     [Asterisk Users]     [PJ SIP]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Linux API]

  Powered by Linux