[Home]

Summary:ASTERISK-23941: ARI: Attended transfers of channels into Stasis application lose information
Reporter:Matt Jordan (mjordan)Labels:
Date Opened:2014-06-25 18:46:51Date Closed:2014-08-07 10:24:39
Priority:MajorRegression?
Status:Closed/CompleteComponents:Core/Bridging Resources/res_ari
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:
Description:When performing a SIP level attended transfer into Stasis, insufficient information is presented for an external application to adequately handle what just occurred.

For example: when a PJSIP channel enters into a Stasis application as the second leg of an attended transfer, when the attended transfer completes, a masquerade and/or a bridge swap may be performed to replace the existing PJSIP channel. Because a new channel is coming into a Stasis application, the following must occur:
# A StasisStart event must be emitted for the channel entering into the Stasis application.
# The attended transfer event must inform the ARI client of the channels involved, including the channel taking the place of the channel leaving the application.
# A StasisEnd event must be emitted for the channel leaving the Stasis application.
Comments:By: Kinsey Moore (kmoore) 2014-07-02 15:11:34.823-0500

The current behavior of Stasis() in regard to attended transfers as demonstrated in tests/rest_api/bridges/attended_transfer is as follows:
* Swap transfers are allowed with the Stasis()-controlled bridge
** This results in situations where non-Stasis()-controlled channels are allowed into Stasis()-controlled bridges
* ARI applications are not directly notified that swap operations have occurred
** It sees a BridgeAttendedTransfer message mention a channel it controls
** It sees its controlled channel exit the bridge, exit Stasis(), and hangup
** It sees a new uncontrolled channel enter a bridge it controls with no indication that it is replacing the channel that hungup
*** The swap field in the json blob defines the uniqueid of the channel that is being swapped, but that does not get passed on to Stasis() event consumers.

Conclusion: Stasis() must know about any channels being swapped out and it must also control the resultant channel.

The paths forward:

Option 1: Forbid Swap Transfers Again
* Reinstate swap prevention flags for all ARI bridges (easy)
* Write masquerade fixup code to notify ARI that the name of its channel has changed (easy-moderate)
* Optionally, write bridging code to allow double-masquerade transfers (easy-moderate)
** This would allow app-local-app transfers to occur
** This would require a new stasis attended transfer message variant
* In this case, Stasis() would behave similarly to ConfBridge(); it would not participate outside itself in the bridging framework

Option 2: Forge Onward with Attended Transfers
* Add new stasis attended transfer message variant for instances where local channels are required to accomplish the bridge (easy)
** This allows Stasis() to notify ARI consumers that their channel is being replaced with another
* Intercept channels entering Stasis()-controlled bridges (unknown difficulty)
** Force them into Stasis() before adding them into the bridge via Stasis() channel control mechanisms

Option 3: Other?

By: Matt Jordan (mjordan) 2014-07-02 16:24:46.615-0500

I think the answer is Option #2, coupled with requiring an interception of channels entering Stasis bridges.

From the perspective of an ARI user, all I know is that I was controlling a channel, and something caused someone else to take its place. I have to think that I own that channel to - after all, the channel that it replaced *was* in my application.

Since this is in the bridging framework, we should use a subclass of a bridge to mange this for Stasis. Implicit in this now is that if you are in a Stasis controlled bridge, you get a subscription to the channel in the bridge. That's probably a good thing in the long run.

By: Kinsey Moore (kmoore) 2014-07-08 21:04:01.928-0500

The solution to this comes in three parts:
* new attended transfer message subtype: https://reviewboard.asterisk.org/r/3728/
* functionality required to queue prestart commands for Stasis(): https://reviewboard.asterisk.org/r/3729/
* functionality to intercept channels entering stasis-controlled bridges and re-route them through Stasis() into the appropriate bridge and under the control of the channel they're replacing: https://reviewboard.asterisk.org/r/3731/

The test updates can be found here: https://reviewboard.asterisk.org/r/3732/