Hello again,

Not sure if this is the right place to post this or not as it is kinda-sorta 
development related; my apologies if I have erred.  Is this only a users' 
forum, and GUI-related development topics should go to asterisk-dev, even 
though nobody there will probably be interested in anything related to the GUI? 
:)

As I've mentioned a couple of times in the past, I have been working on an 
embedded platform that I'm trying to create a turn-key Asterisk + Asterisk-GUI 
system for.  Along the way, I've had to engage in some bug-hunting.  While 
there have been a number of genuine bugs in the GUI code itself that I've 
encountered, I'd say that a sizable number of the issues I've found myself 
wrestling with are simply the result of underlying changes that happened to 
Asterisk between 1.4 and 1.8 that have not yet been accounted for in the GUI.  
For the most part, to my own relief, I've found that the fixes for most of 
these issues (both the genuine bugs as well as the 1.8 incompatibilities) have 
turned out to be fairly straightforward to address, and not demanding of 
sweeping architectural changes or complete rewrites of large blocks of code.

But now I'm wrestling with queues, and at first glance they seem to be nothing 
short of a mess.  I'm trying to figure out the best ways to address the 
problems I'm seeing.  Both the "traditional" chan_agent/AgentLogin() queues and 
the callback-style queues are broken as things currently stand:

1. Classic / AgentLogin()

AgentLogin() is broken on account of SVN changeset 5030, which, in an attempt 
to fix the callback-style queues for Asterisk 1.8, changed queues.js behavior 
so that it added the SIP channel for the agent as a member of the queue (in 
queues.conf) instead of the Agent channel for the agent, as before (so, "member 
= Agent/101" became "member = SIP/101", for example).  This makes sense 
(...kind of, as I'll address when I talk about the callback-style queue), but I 
suspect a better fix would have been to add *both* Agent/101 and SIP/101 as 
queue members, which would have allowed AgentLogin() to continue to work as 
before, instead of completely replacing the former with the latter.  (Either 
that or deprecate support of AgentLogin() in Asterisk-GUI altogether by 
removing the "Agent Login Extension" setting; its continued existence suggests 
that it should still work and be usable.)

2. Callback-style

In Asterisk 1.4, adding Agent channels as static members of queues worked 
universally for both styles of queues, since the callback-style queue was 
implemented using AgentCallbackLogin().  As is well-known by now, 
AgentCallbackLogin() was deprecated in 1.6 and eliminated altogether in 1.8, 
and the official replacement for it was to implement your own callback queue 
within the dialplan itself, using AddQueueMember() and RemoveQueueMember() to 
dynamically add the actual user's channel to the queue -- whether that be SIP, 
IAX2, DAHDI, or whatever -- instead of statically adding a virtual 
pseudo-channel (such as Agent) that is bound to your real channel through a 
login process.  This is what Asterisk-GUI SVN changeset 5030 implemented: a 
replacement for AgentCallbackLogin() in the dialplan.  Aside from the fact that 
this implementation does not prompt for a password/PIN upon logging in (in 
contrast to both AgentLogin() and AgentCallbackLogin()), and also assumes that 
the agent ID is equal to the extension # that the agent is logged on to 
(something that AgentLogin() doesn't assume, and something that 
AgentCallbackLogin() did not assume), the actual dialplan implementation seems 
to work as designed.  But when combined with the GUI itself and how it tracks 
queue members, it is not usable.

>From the user's perspective, the main problem that one will face is that after 
>adding a user with "Is Agent?" checked to a queue, that user will find that 
>he/she cannot log in or log out of the queue by dialing the "Agent Callback 
>Login Extension".  They will simply be told there was an error when they try.  
>Furthermore, they will find that they are actually logged into the queue, 
>permanently.

This is because when you add an agent to a queue in the GUI by checking the 
checkbox next to the agent's extension # in the queue's settings, queues.js 
adds a (for example, in the case of a SIP extension numbered 101) "member = 
SIP/101" to that queue's section in queues.conf.  What this does is add channel 
SIP/101 to the queue as a static member, and static queue members cannot be 
removed by RemoveQueueMember(); only members added via AddQueueMember() can be 
removed by the corresponding removal application.  So, in effect, when you 
configure a queue member using the GUI, that member can never log off, which 
kind of defeats the purpose of having an "Agent Callback Login Extension" as 
well as the entire 'queue-member-manager' apparatus that was added to the 
dialplan.  queues.js links the state of that queue member's checkbox in the GUI 
to the "member" entry that it added to queues.conf, so if you remove that line 
from queues.conf, the checkbox in the GUI will be unchecked.  But at least the 
agent can log on and off at that point, although even that does not behave 
entirely as one might expect.

Here is the behavior of the system as things stand now:

1. "Agent Login Extension" doesn't work.  The agent can log in and everything, 
but when a call enters the queue, it will not be sent to the active 
AgentLogin() session.  If they have been added to a queue via the GUI, because 
doing so adds the agent's direct channel to the queue as a static member, the 
queue will ring the phone directly, completely outside of their AgentLogin() 
session.

2. If a user has "Is Agent?" checked in their user settings, but has not been 
added as members to any queues via the GUI, that user can log in to ALL queues 
simultaneously by simply dialing the "Agent Callback Login Extension".  They 
will then begin to receive calls from all queues defined in the system that are 
getting calls sent to them.

3. If an agent is added to a queue via the GUI, again, because doing so adds 
the agent's direct channel to the queue as a static member, they will find that 
they are permanently "logged in" to that particular queue.  Dialing the "Agent 
Callback Login Extension" will not log them out of that queue, but WILL have 
the effect of proceeding to add them to all other queues defined in the system, 
even though according to the GUI, they are not configured to be members of them!

I think we can agree that this is broken.  This, I believe, is the expected 
behavior of the system, and how things used to work:

1. You enable users to be agents via "Is Agent?" in that user's settings.  
Doing so does not cause them to participate in any queues, but merely makes 
them show up as an option when you go to add members to queues in the GUI (as 
well as defines an Agent channel for them, by virtue of 'hasagent' having been 
set to 'yes' in users.conf, which chan_agent keys off of in addition to parsing 
agents.conf)

2. If an agent dials the "Agent Login Extension", they will have an active 
session with the AgentLogin() application, which will send them calls *over 
that existing session*; if they end the session, they will not get queue calls.

3. If an agent dials the "Agent Callback Login Extension", their phone will be 
sent calls only from queues that they were configured to be members of via the 
GUI, not ALL queues in the system.  Dialing it a second time should cause them 
to no longer get any calls.

I believe the heart of the problem is that although the new dialplan code uses 
AddQueueMember() and RemoveQueueMember() correctly, the GUI, which was 
originally written under the assumption that Agent channels needed to be static 
members of queues, was changed to merely add the agent's direct channel as a 
static queue member instead, which is not a sufficient modification to 
accommodate the new callback method.  The GUI changes need to be more extensive 
than that to account for the new dialplan logic, especially if the desire is to 
continue to support both types of queues, since AgentLogin() *still* requires 
that Agent channels be static members of their respective queues, while the new 
method of implementing callback-style queues most emphatically cannot work that 
way.  This suggests that the state of a queue's member roster in the GUI cannot 
be held merely in the "member =" lines in queues.conf, as the GUI is attempting 
to do now, and needs to be stored elsewhere (a dialplan global variable, 
perhaps? Or -- better yet -- maybe a ${HASH()}?).  The deprecation of 
AgentCallbackLogin() really has caused complications that need to be worked 
through more thoroughly.

A rearchitecting of the GUI's queue support is probably the best way to go 
about a fix, but it also occurred to me that there are a couple of other ways 
that the problem could be solved that would not require extensive rewrites to 
the GUI's queues support.  Instead, minor changes to Asterisk itself would be 
required:

1. Static queue members (that is, members defined in queues.conf) cannot be 
removed from a queue with RemoveQueueMember().  But is there a good reason why 
that is the case?  What if app_queue were modified to allow for that?  A brief 
study of app_queue.c suggests that this would effectively be a one-line change 
(basically, setting the "dynamic" member of the "member" struct to 1 in the 
reload_single_member() function).  This would effectively get rid of static 
queue members, and turn the "member =" lines in queues.conf into a default 
login state of sorts.  This would mean that the Asterisk-GUI could continue to 
utilize those "member" lines in the config file as the means of storing queue 
membership state.  The only possibly negative consequence this might have is 
that users added to queues in the GUI would find themselves logged into their 
respective queues by default after a fresh launch of Asterisk.  It would 
probably best to toggle this new behavior on and off with some kind of new 
global setting in queues.conf that is off by default.

2. RemoveQueueMember() cannot remove static members, but even static members 
can be paused and unpaused with PauseQueueMember() and UnpauseQueueMember().  
Although this is probably not really how their designer(s) intended for them to 
be used, the AddQueueMember() application could be replaced in the dialplan 
with UnpauseQueueMember(), and RemoveQueueMember() with PauseQueueMember().  
The only problem with this is that in order to determine whether someone is 
logged into a queue or not, the current dialplan logic checks to see whether a 
channel is a member of a queue using the ${QUEUE_MEMBER_LIST()} function, which 
counts on the behavior of AddQueueMember() and RemoveQueueMember().  There is 
no function that app_queue exports which returns a list that only consists of 
queue members that are unpaused.  If such a function (say, 
${QUEUE_MEMBER_UNPAUSED_LIST()}) were to be implemented in app_queue, then we 
could get away with pausing and unpausing queue members instead of dynamically 
adding and removing them from queues entirely.  This would have the same effect 
-- allowing the GUI queue member state to remain in queues.conf -- as the 
previous suggestion, but unlike the previous suggestion, would do so without 
eliminating the distinction between static queue members and dynamic queue 
members.  It would also have the same sole negative consequence, in that queue 
members would find themselves logged in by default after an Asterisk restart.

And that's just in order to fix things such that they work again the way they 
(largely) used to work, and are supposed to work.  It doesn't address things 
like:

1. ...giving agents a way to only be logged into certain queues, instead of the 
current all-or-nothing approach
2. ...prompting agents for a PIN when they use the callback-style method (which 
*did* work in the past)
3. ...divorcing the agent ID from the extension number (which also used to be 
the case with the old callback system)

...although some might argue that #3 is not necessarily desireable, and that as 
a matter of principle, agents should be registering to Asterisk using their own 
credentials to begin with.  I'd agree, but it leaves too many other problems 
unresolved.  For example, that policy might work for softphones, but many 
(most?) SIP desk phones do not make switching between SIP users easy, or even 
possible (especially if the phone is locked-down); you can't normally sit down 
at one and punch in a few buttons to "log in" (register to a SIP registrar with 
your own credentials).  Besides, what about other channel technologies, like 
DAHDI?  What if a call center has analog handsets, and yet still needs for 
agents to be able to sit down at any desk and begin to take calls rather than 
providing each agent with a designated phone?

Anyway, this write-up has gone on longer than I'd planned, so I'll stop here 
for now and see if there are any comments (or a recommendation to take the 
discussion elsewhere!).

Thanks,

-- 
Nathan Anderson
First Step Internet, LLC
nath...@fsr.com

--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-gui mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/asterisk-gui

Reply via email to