[Home]

Summary:ASTERISK-22814: GROUP broken for attended transfer (Both SIP transfer and features.conf)
Reporter:Matt King, M.A. Oxon. (kebl0155)Labels:
Date Opened:2013-11-01 12:05:25Date Closed:2013-12-07 20:58:59.000-0600
Priority:MajorRegression?
Status:Closed/CompleteComponents:Functions/func_groupcount
Versions:1.8.15.0 11.6.0 Frequency of
Occurrence
Constant
Related
Issues:
Environment:Debian linux, SIP.Attachments:
Description:A common use for call centres is to restrict phones to give busy tone if one line is busy on a phone and a further incoming call is placed, while leaving a second line free for outbound calls and attended transfers.  This ensures that the queue will move swiftly on to other agents if the phone is already in use, which is highly desirable.

The recommended way to handle this in the dialplan is by using the GROUP and GROUPCOUNT functions.

However, problems arise when an attended transfer is made, using EITHER SIP attended transfer direct from the phone, OR the mechanism specified in features.conf

Specifically, the Group is NOT cleared when the original phone drops out of the call at the end of the transfer.  Instead, the Group is only cleared when the final party hangs up.

This leaves the agent unable to take further calls until the transferred call completes.

See below for steps to reproduce.

This problem has been found with SIP phones. It is unknown whether other channel types are affected, however this seems highly probable as the Group function is channel type agnostic.
Comments:By: Rusty Newton (rnewton) 2013-11-13 16:48:43.600-0600

As far as I can see, with the way GROUP and GROUP_COUNT work, things are operating as expected with your example.

I've only used the GROUP functions and variables a few times, but I did a little reading and worked this out:

{noformat}
exten => _6XXX,1,NoOp(Dialling phone ${EXTEN})
;Set the group for the current channel to name of the associated peer
exten => _6XXX,n,Set(GROUP()=${CHANNEL(peername)})
;Set the default group for the to-be-dialed/destination channel, to the extension we are dialing
exten => _6XXX,n,Set(OUTBOUND_GROUP=${EXTEN})
;Check the number of channels for the group of the extension/peer we are dialing
exten => _6XXX,n,GotoIf($[${GROUP_COUNT(${EXTEN})} > 1]?busy,1)
exten => _6XXX,n,Dial(SIP/${EXTEN},,rotTwhk)
exten => _6XXX,n,Hangup

exten => busy,1,Hangup(17)
{noformat}

With this, both of your test scenarios work fine

Here is what 'group show channels' looks like when X003 has answered X002 during the attended part of the attended transfer:

{noformat}
newtonr-laptop*CLI> group show channels
Channel                    Group                 Category            
SIP/6001-00000000          6001                  (default)          
SIP/6002-00000001          6002                  (default)          
SIP/6002-00000002          6002                  (default)          
SIP/6003-00000003          6003                  (default)          
4 active channels
{noformat}

and then after X002 completes the transfer

{noformat}
newtonr-laptop*CLI> group show channels
Channel                    Group                 Category            
SIP/6001-00000000          6001                  (default)          
SIP/6003-00000003          6003                  (default)          
2 active channels
{noformat}

If you try to dial X002 from X004 when it has two channels in it's group, then X004 will busy out as expected. Otherwise, X004 can dial any of the extensions with only a single channel in it's group during the process.

I don't see a bug here. Let me know if I misunderstood the behavior. Thanks!


By: Rusty Newton (rnewton) 2013-11-13 16:59:02.656-0600

Also, from 'core show application dial' help text, in case it is useful:

{noformat}
If the ${OUTBOUND_GROUP} variable is set, all peer channels created by this
application will be put into that group (as in Set(GROUP()=...). If the $
{OUTBOUND_GROUP_ONCE} variable is set, all peer channels created by this
application will be put into that group (as in Set(GROUP()=...). Unlike $
{OUTBOUND_GROUP}, however, the variable will be unset after use.
{noformat}