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