Skip to main content

iSymphony error when forwarding calls

Posted by fuse3 on Fri, 03/15/2013

I am having an issue when a customer forwards a calls with iSymphony. If he forwards them manually with the phone they work correctly but with the iSymphony application it fails. I have set the originating context and redirecting context to "from-inside". Also tried a redirecting context of "from-inside-redir". All fails when sending the call, it will ring the user twice and hang up the call.

Call Flow:
Inbound call is forwarded to an extension based ring group.
User picks up and drags the call to the remote extension and it rings twice and fails
Or user pushes transfer on his handset and types the extension and it goes through fine

I opened a ticket with iSymphony and they have come to the conclusion that this is caused by the way TL is handling the call.

TL STE: 6.1.1.12
CentOS 6.3 x64
Asterisk 1.8.20.1

Here is the email from the excellent support team at iSymphony :). They explain the technical details.

"It looks as if the issue is rooted in the fact that the channel that is being transferred via iSymphony is not the local channel of the original call that is proxying the channel from the trunk.

The channel relationships in the original call before it is transferred looks like so:

SIP/FUSE3-ACME-SMF-HA1-xxxx ------> Local/101@from-inside-xxxxxxx;1
Local/101@from-inside-xxxxxxx;2 --------> SIP/101-xxxxxx

In this case the local channels are proxying the original channels in order to perform advanced dialplan logic. The issues seems to occur in the fact that the phone itself is transferring the local channel (Local/101@from-inside-xxxxxxx;2) instead of the physical channel (SIP/FUSE3-ACME-SMF-HA1-xxxx) as iSymphony does.

iSymphony transfer:
-- Local/101@from-inside-000001bc;1 answered SIP/FUSE3-ACME-SMF-HA1-00000569
-- Executing [h@from-inside-redir:1] Hangup("Local/101@from-inside-000001bc;2", "") in new stack
== Spawn extension (from-inside, 110, 1) exited non-zero on 'SIP/FUSE3-ACME-SMF-HA1-00000569' in macro 'tl-ringgroup-base'
== Spawn extension (from-inside, 110, 1) exited non-zero on 'SIP/FUSE3-ACME-SMF-HA1-00000569'

Phone transfer:
-- Local/101@from-inside-000004a0;1 answered SIP/FUSE3-ACME-SMF-HA1-00000fcd
== Spawn extension (from-inside, 110, 1) exited non-zero on 'Local/101@from-inside-000004a0;2' in macro 'tl-userexten-rg-base'
== Spawn extension (from-inside, 110, 1) exited non-zero on 'Local/101@from-inside-000004a0;2' in macro 'tl-userexten'

The Thirdlane dialplan seems to handle these two channels in a very different way causing the low ring time and the bypass of the Voicemail logic. It seems as if the Thirdlane dialplan was not build to handle the transfer of physical channels. iSymphony will not perform actions on local channels only physical channels in the channel stream in attempt to cover the majority of dialplan implementations which usually contain support for both physical and local channels.

It seems as if we need to get Thirdlane involved in order to resolve this issue. I can attempt to contact them or you can make the contact directly. Please let me know how you would like to move forward."


Submitted by eeman on Tue, 03/19/2013 Permalink

Michael contacted me via email and hired me to take a look at his problem. After analyzing the call flow it appears the problem was tied to extension-based ring groups and their use of RINGGROUP_TIMEOUT. before I get into the solution and explanation as to why it was failing, first a bit of history of how this variable evolved.

HISTORY
In the beginning the only ring group was a extension based ring group. Dialplan was created that called a ringgroup-base macro that created a Dial application for each extension in a list but using a chan_local.so designation of Local/101&Local/102&Local/103 etc. The problem quickly arose that if someone's phone was set to go to VM after only a couple rings, or if they had FM/FM enabled, that the other members simply were never given the chance to answer the call because this extension had already answered the call in some fashion.

To address this issue, the value RINGGROUP_TIMEOUT was born so that if the tl-userexten script detected this variable, it bypassed the tl-userexten-base script entirely and diverted the call to tl-userexten-rg-base instead which has a very limited feature set. This was very messy and often involved chan_local not just once but as many as three times for a single call. Caller -> sip-trunk -> chan_local -> chan_local -> chan_sip -> Callee.

When asterisk 1.4 released a new option 'i' existed that resolved a previous problem with calling devices directly. Until then when you called SIP/101&SIP/102&SIP/103, if one of the phones had forwarding enabled asterisk would receive a 302 "Moved Temporarily" message and stop inviting the other members of that group and begin a new dial operation for this forwarded number. We called this 'hijacking the ring group'. The i option tells the Dial application to ignore all forwarding messages from the device. This was a major relief to anyone fighting with ring groups and users who wanted to forward calls from their phones.

Eventually other chan_local problems started to appear like DTMF not working when chan_local was in the middle of a bridge etc. With the release of 1.4 and my arrival in the community, I pressed Alex to make another option called Device Based ring groups where you could specify the sip device instead of this round-about approach to calling the phones. The dialplan was much cleaner, and unless you used the 'other numbers to dial' chan_local never got invoked.

Analysis
So now that you understand the history and what the variable did, now lets look at why it breaks an isymphony transfer. iSymphony does a redirect of the leg of the call to a new device. This is much like the way polycom does a blind transfer. Essentially the calling leg is disconnected and re-attached to dialplan for the new extension. Remember that RINGGROUP_TIMEOUT variable I mentioned? Well its still present on the calling leg of the call. So when the caller runs through dialplan for the 'transfer' the tl-userexten script detects this variable and sends the caller to tl-userexten-rg-base. So the device still gets called, but now the dial command is timing out after RINGGROUP_TIMEOUT amount of seconds. In this case that was only 12 seconds, or 2 rings. Since the tl-userexten-rg-base script existed to bypass VM and FM/FM, it ran out of dialplan so the call just ends.

Solution
There are two solutions to the issue.

  1. use device based ring groups. since the variable never gets set the behavior will be exactly what you expected.
  2. create a custom context that strips the variable first before sending it along

since they were already using extension based ring groups, and I wasnt sure if they had one of those very obscure needs that precluded device based, I built #2 for them

in /etc/asterisk/user_extensions.include I created a context from-inside-redir-isymphony with a basic 2 line dialplan.

[from-inside-redir-isymphony]
exten => _X.,1,Set(__RINGGROUP_TIMEOUT=)
exten => _X.,n,Goto(from-inside-redir,${EXTEN},1)

then the matter was a simple as setting the redirect context in iSymphony to from-inside-redir-isymphony. Now iSymphony will redirect here, the variable gets stripped, then its sent back to the from-inside-redir context it should have arrived to in the first place.