A great big renaming patch
[asterisk/asterisk.git] / apps / app_queue.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief True call queues with optional send URL on answer
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \par Development notes
26  * \note 2004-11-25: Persistent Dynamic Members added by:
27  *             NetNation Communications (www.netnation.com)
28  *             Kevin Lindsay <kevinl@netnation.com>
29  *
30  *             Each dynamic agent in each queue is now stored in the astdb.
31  *             When asterisk is restarted, each agent will be automatically
32  *             readded into their recorded queues. This feature can be
33  *             configured with the 'persistent_members=<1|0>' setting in the
34  *             '[general]' category in queues.conf. The default is on.
35  *
36  * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
37  *
38  * \note These features added by David C. Troy <dave@toad.net>:
39  *    - Per-queue holdtime calculation
40  *    - Estimated holdtime announcement
41  *    - Position announcement
42  *    - Abandoned/completed call counters
43  *    - Failout timer passed as optional app parameter
44  *    - Optional monitoring of calls, started when call is answered
45  *
46  * Patch Version 1.07 2003-12-24 01
47  *
48  * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
49  * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
50  *
51  * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
52  * by Matthew Enger <m.enger@xi.com.au>
53  *
54  * \ingroup applications
55  */
56
57 /*! \li \ref app_queues.c uses configuration file \ref queues.conf
58  * \addtogroup configuration_file
59  */
60
61 /*! \page queues.conf queues.conf
62  * \verbinclude queues.conf.sample
63  */
64
65 /*** MODULEINFO
66         <use type="module">res_monitor</use>
67         <support_level>core</support_level>
68  ***/
69
70 #include "asterisk.h"
71
72 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
73
74 #include <sys/time.h>
75 #include <sys/signal.h>
76 #include <netinet/in.h>
77 #include <ctype.h>
78
79 #include "asterisk/lock.h"
80 #include "asterisk/file.h"
81 #include "asterisk/channel.h"
82 #include "asterisk/pbx.h"
83 #include "asterisk/app.h"
84 #include "asterisk/linkedlists.h"
85 #include "asterisk/module.h"
86 #include "asterisk/translate.h"
87 #include "asterisk/say.h"
88 #include "asterisk/features.h"
89 #include "asterisk/musiconhold.h"
90 #include "asterisk/cli.h"
91 #include "asterisk/manager.h"
92 #include "asterisk/config.h"
93 #include "asterisk/monitor.h"
94 #include "asterisk/utils.h"
95 #include "asterisk/causes.h"
96 #include "asterisk/astdb.h"
97 #include "asterisk/devicestate.h"
98 #include "asterisk/stringfields.h"
99 #include "asterisk/event.h"
100 #include "asterisk/astobj2.h"
101 #include "asterisk/strings.h"
102 #include "asterisk/global_datastores.h"
103 #include "asterisk/taskprocessor.h"
104 #include "asterisk/aoc.h"
105 #include "asterisk/callerid.h"
106 #include "asterisk/data.h"
107 #include "asterisk/term.h"
108 #include "asterisk/dial.h"
109 #include "asterisk/stasis_channels.h"
110 #include "asterisk/stasis_message_router.h"
111 #include "asterisk/bridge_after.h"
112
113 /* Define, to debug reference counts on queues, without debugging reference counts on queue members */
114 /* #define REF_DEBUG_ONLY_QUEUES */
115
116 /*!
117  * \par Please read before modifying this file.
118  * There are three locks which are regularly used
119  * throughout this file, the queue list lock, the lock
120  * for each individual queue, and the interface list lock.
121  * Please be extra careful to always lock in the following order
122  * 1) queue list lock
123  * 2) individual queue lock
124  * 3) interface list lock
125  * This order has sort of "evolved" over the lifetime of this
126  * application, but it is now in place this way, so please adhere
127  * to this order!
128  */
129
130 /*** DOCUMENTATION
131         <application name="Queue" language="en_US">
132                 <synopsis>
133                         Queue a call for a call queue.
134                 </synopsis>
135                 <syntax>
136                         <parameter name="queuename" required="true" />
137                         <parameter name="options">
138                                 <optionlist>
139                                         <option name="C">
140                                                 <para>Mark all calls as "answered elsewhere" when cancelled.</para>
141                                         </option>
142                                         <option name="c">
143                                                 <para>Continue in the dialplan if the callee hangs up.</para>
144                                         </option>
145                                         <option name="d">
146                                                 <para>data-quality (modem) call (minimum delay).</para>
147                                         </option>
148                                         <option name="F" argsep="^">
149                                                 <argument name="context" required="false" />
150                                                 <argument name="exten" required="false" />
151                                                 <argument name="priority" required="true" />
152                                                 <para>When the caller hangs up, transfer the <emphasis>called member</emphasis>
153                                                 to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
154                                                 <note>
155                                                         <para>Any channel variables you want the called channel to inherit from the caller channel must be
156                                                         prefixed with one or two underbars ('_').</para>
157                                                 </note>
158                                         </option>
159                                         <option name="F">
160                                                 <para>When the caller hangs up, transfer the <emphasis>called member</emphasis> to the next priority of
161                                                 the current extension and <emphasis>start</emphasis> execution at that location.</para>
162                                                 <note>
163                                                         <para>Any channel variables you want the called channel to inherit from the caller channel must be
164                                                         prefixed with one or two underbars ('_').</para>
165                                                 </note>
166                                                 <note>
167                                                         <para>Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>
168                                                 </note>
169                                         </option>
170                                         <option name="h">
171                                                 <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
172                                         </option>
173                                         <option name="H">
174                                                 <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
175                                         </option>
176                                         <option name="n">
177                                                 <para>No retries on the timeout; will exit this application and
178                                                 go to the next step.</para>
179                                         </option>
180                                         <option name="i">
181                                                 <para>Ignore call forward requests from queue members and do nothing
182                                                 when they are requested.</para>
183                                         </option>
184                                         <option name="I">
185                                                 <para>Asterisk will ignore any connected line update requests or any redirecting party
186                                                 update requests it may receive on this dial attempt.</para>
187                                         </option>
188                                         <option name="r">
189                                                 <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
190                                         </option>
191                                         <option name="R">
192                                                 <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
193                                         </option>
194                                         <option name="t">
195                                                 <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
196                                         </option>
197                                         <option name="T">
198                                                 <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
199                                         </option>
200                                         <option name="w">
201                                                 <para>Allow the <emphasis>called</emphasis> user to write the conversation to
202                                                 disk via Monitor.</para>
203                                         </option>
204                                         <option name="W">
205                                                 <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
206                                                 disk via Monitor.</para>
207                                         </option>
208                                         <option name="k">
209                                                 <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
210                                                 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
211                                         </option>
212                                         <option name="K">
213                                                 <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
214                                                 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
215                                         </option>
216                                         <option name="x">
217                                                 <para>Allow the <emphasis>called</emphasis> user to write the conversation
218                                                 to disk via MixMonitor.</para>
219                                         </option>
220                                         <option name="X">
221                                                 <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
222                                                 disk via MixMonitor.</para>
223                                         </option>
224                                 </optionlist>
225                         </parameter>
226                         <parameter name="URL">
227                                 <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
228                         </parameter>
229                         <parameter name="announceoverride" />
230                         <parameter name="timeout">
231                                 <para>Will cause the queue to fail out after a specified number of
232                                 seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
233                                 <replaceable>retry</replaceable> cycle.</para>
234                         </parameter>
235                         <parameter name="AGI">
236                                 <para>Will setup an AGI script to be executed on the calling party's channel once they are
237                                 connected to a queue member.</para>
238                         </parameter>
239                         <parameter name="macro">
240                                 <para>Will run a macro on the calling party's channel once they are connected to a queue member.</para>
241                         </parameter>
242                         <parameter name="gosub">
243                                 <para>Will run a gosub on the calling party's channel once they are connected to a queue member.</para>
244                         </parameter>
245                         <parameter name="rule">
246                                 <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
247                         </parameter>
248                         <parameter name="position">
249                                 <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
250                                 would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
251                                 the caller third in the queue.</para>
252                         </parameter>
253                 </syntax>
254                 <description>
255                         <para>In addition to transferring the call, a call may be parked and then picked
256                         up by another user.</para>
257                         <para>This application will return to the dialplan if the queue does not exist, or
258                         any of the join options cause the caller to not enter the queue.</para>
259                         <para>This application does not automatically answer and should be preceeded
260                         by an application such as Answer(), Progress(), or Ringing().</para>
261                         <para>This application sets the following channel variable upon completion:</para>
262                         <variablelist>
263                                 <variable name="QUEUESTATUS">
264                                         <para>The status of the call as a text string.</para>
265                                         <value name="TIMEOUT" />
266                                         <value name="FULL" />
267                                         <value name="JOINEMPTY" />
268                                         <value name="LEAVEEMPTY" />
269                                         <value name="JOINUNAVAIL" />
270                                         <value name="LEAVEUNAVAIL" />
271                                         <value name="CONTINUE" />
272                                 </variable>
273                         </variablelist>
274                 </description>
275                 <see-also>
276                         <ref type="application">Queue</ref>
277                         <ref type="application">QueueLog</ref>
278                         <ref type="application">AddQueueMember</ref>
279                         <ref type="application">RemoveQueueMember</ref>
280                         <ref type="application">PauseQueueMember</ref>
281                         <ref type="application">UnpauseQueueMember</ref>
282                         <ref type="function">QUEUE_VARIABLES</ref>
283                         <ref type="function">QUEUE_MEMBER</ref>
284                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
285                         <ref type="function">QUEUE_EXISTS</ref>
286                         <ref type="function">QUEUE_WAITING_COUNT</ref>
287                         <ref type="function">QUEUE_MEMBER_LIST</ref>
288                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
289                 </see-also>
290         </application>
291         <application name="AddQueueMember" language="en_US">
292                 <synopsis>
293                         Dynamically adds queue members.
294                 </synopsis>
295                 <syntax>
296                         <parameter name="queuename" required="true" />
297                         <parameter name="interface" />
298                         <parameter name="penalty" />
299                         <parameter name="options" />
300                         <parameter name="membername" />
301                         <parameter name="stateinterface" />
302                 </syntax>
303                 <description>
304                         <para>Dynamically adds interface to an existing queue. If the interface is
305                         already in the queue it will return an error.</para>
306                         <para>This application sets the following channel variable upon completion:</para>
307                         <variablelist>
308                                 <variable name="AQMSTATUS">
309                                         <para>The status of the attempt to add a queue member as a text string.</para>
310                                         <value name="ADDED" />
311                                         <value name="MEMBERALREADY" />
312                                         <value name="NOSUCHQUEUE" />
313                                 </variable>
314                         </variablelist>
315                 </description>
316                 <see-also>
317                         <ref type="application">Queue</ref>
318                         <ref type="application">QueueLog</ref>
319                         <ref type="application">AddQueueMember</ref>
320                         <ref type="application">RemoveQueueMember</ref>
321                         <ref type="application">PauseQueueMember</ref>
322                         <ref type="application">UnpauseQueueMember</ref>
323                         <ref type="function">QUEUE_VARIABLES</ref>
324                         <ref type="function">QUEUE_MEMBER</ref>
325                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
326                         <ref type="function">QUEUE_EXISTS</ref>
327                         <ref type="function">QUEUE_WAITING_COUNT</ref>
328                         <ref type="function">QUEUE_MEMBER_LIST</ref>
329                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
330                 </see-also>
331         </application>
332         <application name="RemoveQueueMember" language="en_US">
333                 <synopsis>
334                         Dynamically removes queue members.
335                 </synopsis>
336                 <syntax>
337                         <parameter name="queuename" required="true" />
338                         <parameter name="interface" />
339                 </syntax>
340                 <description>
341                         <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
342                         <para>This application sets the following channel variable upon completion:</para>
343                         <variablelist>
344                                 <variable name="RQMSTATUS">
345                                         <value name="REMOVED" />
346                                         <value name="NOTINQUEUE" />
347                                         <value name="NOSUCHQUEUE" />
348                                         <value name="NOTDYNAMIC" />
349                                 </variable>
350                         </variablelist>
351                         <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
352                 </description>
353                 <see-also>
354                         <ref type="application">Queue</ref>
355                         <ref type="application">QueueLog</ref>
356                         <ref type="application">AddQueueMember</ref>
357                         <ref type="application">RemoveQueueMember</ref>
358                         <ref type="application">PauseQueueMember</ref>
359                         <ref type="application">UnpauseQueueMember</ref>
360                         <ref type="function">QUEUE_VARIABLES</ref>
361                         <ref type="function">QUEUE_MEMBER</ref>
362                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
363                         <ref type="function">QUEUE_EXISTS</ref>
364                         <ref type="function">QUEUE_WAITING_COUNT</ref>
365                         <ref type="function">QUEUE_MEMBER_LIST</ref>
366                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
367                 </see-also>
368         </application>
369         <application name="PauseQueueMember" language="en_US">
370                 <synopsis>
371                         Pauses a queue member.
372                 </synopsis>
373                 <syntax>
374                         <parameter name="queuename" />
375                         <parameter name="interface" required="true" />
376                         <parameter name="options" />
377                         <parameter name="reason">
378                                 <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
379                         </parameter>
380                 </syntax>
381                 <description>
382                         <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
383                         This prevents any calls from being sent from the queue to the interface until it is
384                         unpaused with UnpauseQueueMember or the manager interface.  If no queuename is given,
385                         the interface is paused in every queue it is a member of. The application will fail if the
386                         interface is not found.</para>
387                         <para>This application sets the following channel variable upon completion:</para>
388                         <variablelist>
389                                 <variable name="PQMSTATUS">
390                                         <para>The status of the attempt to pause a queue member as a text string.</para>
391                                         <value name="PAUSED" />
392                                         <value name="NOTFOUND" />
393                                 </variable>
394                         </variablelist>
395                         <para>Example: PauseQueueMember(,SIP/3000)</para>
396                 </description>
397                 <see-also>
398                         <ref type="application">Queue</ref>
399                         <ref type="application">QueueLog</ref>
400                         <ref type="application">AddQueueMember</ref>
401                         <ref type="application">RemoveQueueMember</ref>
402                         <ref type="application">PauseQueueMember</ref>
403                         <ref type="application">UnpauseQueueMember</ref>
404                         <ref type="function">QUEUE_VARIABLES</ref>
405                         <ref type="function">QUEUE_MEMBER</ref>
406                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
407                         <ref type="function">QUEUE_EXISTS</ref>
408                         <ref type="function">QUEUE_WAITING_COUNT</ref>
409                         <ref type="function">QUEUE_MEMBER_LIST</ref>
410                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
411                 </see-also>
412         </application>
413         <application name="UnpauseQueueMember" language="en_US">
414                 <synopsis>
415                         Unpauses a queue member.
416                 </synopsis>
417                 <syntax>
418                         <parameter name="queuename" />
419                         <parameter name="interface" required="true" />
420                         <parameter name="options" />
421                         <parameter name="reason">
422                                 <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
423                         </parameter>
424                 </syntax>
425                 <description>
426                         <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
427                         and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
428                         <para>This application sets the following channel variable upon completion:</para>
429                         <variablelist>
430                                 <variable name="UPQMSTATUS">
431                                         <para>The status of the attempt to unpause a queue member as a text string.</para>
432                                         <value name="UNPAUSED" />
433                                         <value name="NOTFOUND" />
434                                 </variable>
435                         </variablelist>
436                         <para>Example: UnpauseQueueMember(,SIP/3000)</para>
437                 </description>
438                 <see-also>
439                         <ref type="application">Queue</ref>
440                         <ref type="application">QueueLog</ref>
441                         <ref type="application">AddQueueMember</ref>
442                         <ref type="application">RemoveQueueMember</ref>
443                         <ref type="application">PauseQueueMember</ref>
444                         <ref type="application">UnpauseQueueMember</ref>
445                         <ref type="function">QUEUE_VARIABLES</ref>
446                         <ref type="function">QUEUE_MEMBER</ref>
447                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
448                         <ref type="function">QUEUE_EXISTS</ref>
449                         <ref type="function">QUEUE_WAITING_COUNT</ref>
450                         <ref type="function">QUEUE_MEMBER_LIST</ref>
451                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
452                 </see-also>
453         </application>
454         <application name="QueueLog" language="en_US">
455                 <synopsis>
456                         Writes to the queue_log file.
457                 </synopsis>
458                 <syntax>
459                         <parameter name="queuename" required="true" />
460                         <parameter name="uniqueid" required="true" />
461                         <parameter name="agent" required="true" />
462                         <parameter name="event" required="true" />
463                         <parameter name="additionalinfo" />
464                 </syntax>
465                 <description>
466                         <para>Allows you to write your own events into the queue log.</para>
467                         <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
468                 </description>
469                 <see-also>
470                         <ref type="application">Queue</ref>
471                         <ref type="application">QueueLog</ref>
472                         <ref type="application">AddQueueMember</ref>
473                         <ref type="application">RemoveQueueMember</ref>
474                         <ref type="application">PauseQueueMember</ref>
475                         <ref type="application">UnpauseQueueMember</ref>
476                         <ref type="function">QUEUE_VARIABLES</ref>
477                         <ref type="function">QUEUE_MEMBER</ref>
478                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
479                         <ref type="function">QUEUE_EXISTS</ref>
480                         <ref type="function">QUEUE_WAITING_COUNT</ref>
481                         <ref type="function">QUEUE_MEMBER_LIST</ref>
482                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
483                 </see-also>
484         </application>
485         <function name="QUEUE_VARIABLES" language="en_US">
486                 <synopsis>
487                         Return Queue information in variables.
488                 </synopsis>
489                 <syntax>
490                         <parameter name="queuename" required="true">
491                                 <enumlist>
492                                         <enum name="QUEUEMAX">
493                                                 <para>Maxmimum number of calls allowed.</para>
494                                         </enum>
495                                         <enum name="QUEUESTRATEGY">
496                                                 <para>The strategy of the queue.</para>
497                                         </enum>
498                                         <enum name="QUEUECALLS">
499                                                 <para>Number of calls currently in the queue.</para>
500                                         </enum>
501                                         <enum name="QUEUEHOLDTIME">
502                                                 <para>Current average hold time.</para>
503                                         </enum>
504                                         <enum name="QUEUECOMPLETED">
505                                                 <para>Number of completed calls for the queue.</para>
506                                         </enum>
507                                         <enum name="QUEUEABANDONED">
508                                                 <para>Number of abandoned calls.</para>
509                                         </enum>
510                                         <enum name="QUEUESRVLEVEL">
511                                                 <para>Queue service level.</para>
512                                         </enum>
513                                         <enum name="QUEUESRVLEVELPERF">
514                                                 <para>Current service level performance.</para>
515                                         </enum>
516                                 </enumlist>
517                         </parameter>
518                 </syntax>
519                 <description>
520                         <para>Makes the following queue variables available.</para>
521                         <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
522                 </description>
523                 <see-also>
524                         <ref type="application">Queue</ref>
525                         <ref type="application">QueueLog</ref>
526                         <ref type="application">AddQueueMember</ref>
527                         <ref type="application">RemoveQueueMember</ref>
528                         <ref type="application">PauseQueueMember</ref>
529                         <ref type="application">UnpauseQueueMember</ref>
530                         <ref type="function">QUEUE_VARIABLES</ref>
531                         <ref type="function">QUEUE_MEMBER</ref>
532                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
533                         <ref type="function">QUEUE_EXISTS</ref>
534                         <ref type="function">QUEUE_WAITING_COUNT</ref>
535                         <ref type="function">QUEUE_MEMBER_LIST</ref>
536                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
537                 </see-also>
538         </function>
539         <function name="QUEUE_MEMBER" language="en_US">
540                 <synopsis>
541                         Count number of members answering a queue.
542                 </synopsis>
543                 <syntax>
544                         <parameter name="queuename" required="true" />
545                         <parameter name="option" required="true">
546                                 <enumlist>
547                                         <enum name="logged">
548                                                 <para>Returns the number of logged-in members for the specified queue.</para>
549                                         </enum>
550                                         <enum name="free">
551                                                 <para>Returns the number of logged-in members for the specified queue that either can take calls or are currently wrapping up after a previous call.</para>
552                                         </enum>
553                                         <enum name="ready">
554                                                 <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
555                                         </enum>
556                                         <enum name="count">
557                                                 <para>Returns the total number of members for the specified queue.</para>
558                                         </enum>
559                                         <enum name="penalty">
560                                                 <para>Gets or sets queue member penalty.</para>
561                                         </enum>
562                                         <enum name="paused">
563                                                 <para>Gets or sets queue member paused status.</para>
564                                         </enum>
565                                         <enum name="ringinuse">
566                                                 <para>Gets or sets queue member ringinuse.</para>
567                                         </enum>
568                                 </enumlist>
569                         </parameter>
570                         <parameter name="interface" required="false" />
571                 </syntax>
572                 <description>
573                         <para>Allows access to queue counts [R] and member information [R/W].</para>
574                         <para>
575                                 <replaceable>queuename</replaceable> is required for all operations
576                                 <replaceable>interface</replaceable> is required for all member operations.
577                         </para>
578                 </description>
579                 <see-also>
580                         <ref type="application">Queue</ref>
581                         <ref type="application">QueueLog</ref>
582                         <ref type="application">AddQueueMember</ref>
583                         <ref type="application">RemoveQueueMember</ref>
584                         <ref type="application">PauseQueueMember</ref>
585                         <ref type="application">UnpauseQueueMember</ref>
586                         <ref type="function">QUEUE_VARIABLES</ref>
587                         <ref type="function">QUEUE_MEMBER</ref>
588                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
589                         <ref type="function">QUEUE_EXISTS</ref>
590                         <ref type="function">QUEUE_WAITING_COUNT</ref>
591                         <ref type="function">QUEUE_MEMBER_LIST</ref>
592                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
593                 </see-also>
594         </function>
595         <function name="QUEUE_MEMBER_COUNT" language="en_US">
596                 <synopsis>
597                         Count number of members answering a queue.
598                 </synopsis>
599                 <syntax>
600                         <parameter name="queuename" required="true" />
601                 </syntax>
602                 <description>
603                         <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
604                         <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
605                 </description>
606                 <see-also>
607                         <ref type="application">Queue</ref>
608                         <ref type="application">QueueLog</ref>
609                         <ref type="application">AddQueueMember</ref>
610                         <ref type="application">RemoveQueueMember</ref>
611                         <ref type="application">PauseQueueMember</ref>
612                         <ref type="application">UnpauseQueueMember</ref>
613                         <ref type="function">QUEUE_VARIABLES</ref>
614                         <ref type="function">QUEUE_MEMBER</ref>
615                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
616                         <ref type="function">QUEUE_EXISTS</ref>
617                         <ref type="function">QUEUE_WAITING_COUNT</ref>
618                         <ref type="function">QUEUE_MEMBER_LIST</ref>
619                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
620                 </see-also>
621         </function>
622         <function name="QUEUE_EXISTS" language="en_US">
623                 <synopsis>
624                         Check if a named queue exists on this server
625                 </synopsis>
626                 <syntax>
627                         <parameter name="queuename" />
628                 </syntax>
629                 <description>
630                         <para>Returns 1 if the specified queue exists, 0 if it does not</para>
631                 </description>
632                 <see-also>
633                         <ref type="application">Queue</ref>
634                         <ref type="application">QueueLog</ref>
635                         <ref type="application">AddQueueMember</ref>
636                         <ref type="application">RemoveQueueMember</ref>
637                         <ref type="application">PauseQueueMember</ref>
638                         <ref type="application">UnpauseQueueMember</ref>
639                         <ref type="function">QUEUE_VARIABLES</ref>
640                         <ref type="function">QUEUE_MEMBER</ref>
641                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
642                         <ref type="function">QUEUE_EXISTS</ref>
643                         <ref type="function">QUEUE_WAITING_COUNT</ref>
644                         <ref type="function">QUEUE_MEMBER_LIST</ref>
645                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
646                 </see-also>
647         </function>
648         <function name="QUEUE_WAITING_COUNT" language="en_US">
649                 <synopsis>
650                         Count number of calls currently waiting in a queue.
651                 </synopsis>
652                 <syntax>
653                         <parameter name="queuename" />
654                 </syntax>
655                 <description>
656                         <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
657                 </description>
658                 <see-also>
659                         <ref type="application">Queue</ref>
660                         <ref type="application">QueueLog</ref>
661                         <ref type="application">AddQueueMember</ref>
662                         <ref type="application">RemoveQueueMember</ref>
663                         <ref type="application">PauseQueueMember</ref>
664                         <ref type="application">UnpauseQueueMember</ref>
665                         <ref type="function">QUEUE_VARIABLES</ref>
666                         <ref type="function">QUEUE_MEMBER</ref>
667                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
668                         <ref type="function">QUEUE_EXISTS</ref>
669                         <ref type="function">QUEUE_WAITING_COUNT</ref>
670                         <ref type="function">QUEUE_MEMBER_LIST</ref>
671                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
672                 </see-also>
673         </function>
674         <function name="QUEUE_MEMBER_LIST" language="en_US">
675                 <synopsis>
676                         Returns a list of interfaces on a queue.
677                 </synopsis>
678                 <syntax>
679                         <parameter name="queuename" required="true" />
680                 </syntax>
681                 <description>
682                         <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
683                 </description>
684                 <see-also>
685                         <ref type="application">Queue</ref>
686                         <ref type="application">QueueLog</ref>
687                         <ref type="application">AddQueueMember</ref>
688                         <ref type="application">RemoveQueueMember</ref>
689                         <ref type="application">PauseQueueMember</ref>
690                         <ref type="application">UnpauseQueueMember</ref>
691                         <ref type="function">QUEUE_VARIABLES</ref>
692                         <ref type="function">QUEUE_MEMBER</ref>
693                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
694                         <ref type="function">QUEUE_EXISTS</ref>
695                         <ref type="function">QUEUE_WAITING_COUNT</ref>
696                         <ref type="function">QUEUE_MEMBER_LIST</ref>
697                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
698                 </see-also>
699         </function>
700         <function name="QUEUE_MEMBER_PENALTY" language="en_US">
701                 <synopsis>
702                         Gets or sets queue members penalty.
703                 </synopsis>
704                 <syntax>
705                         <parameter name="queuename" required="true" />
706                         <parameter name="interface" required="true" />
707                 </syntax>
708                 <description>
709                         <para>Gets or sets queue members penalty.</para>
710                         <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
711                 </description>
712                 <see-also>
713                         <ref type="application">Queue</ref>
714                         <ref type="application">QueueLog</ref>
715                         <ref type="application">AddQueueMember</ref>
716                         <ref type="application">RemoveQueueMember</ref>
717                         <ref type="application">PauseQueueMember</ref>
718                         <ref type="application">UnpauseQueueMember</ref>
719                         <ref type="function">QUEUE_VARIABLES</ref>
720                         <ref type="function">QUEUE_MEMBER</ref>
721                         <ref type="function">QUEUE_MEMBER_COUNT</ref>
722                         <ref type="function">QUEUE_EXISTS</ref>
723                         <ref type="function">QUEUE_WAITING_COUNT</ref>
724                         <ref type="function">QUEUE_MEMBER_LIST</ref>
725                         <ref type="function">QUEUE_MEMBER_PENALTY</ref>
726                 </see-also>
727         </function>
728         <manager name="Queues" language="en_US">
729                 <synopsis>
730                         Queues.
731                 </synopsis>
732                 <syntax>
733                 </syntax>
734                 <description>
735                 </description>
736         </manager>
737         <manager name="QueueStatus" language="en_US">
738                 <synopsis>
739                         Show queue status.
740                 </synopsis>
741                 <syntax>
742                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
743                         <parameter name="Queue" />
744                         <parameter name="Member" />
745                 </syntax>
746                 <description>
747                 </description>
748         </manager>
749         <manager name="QueueSummary" language="en_US">
750                 <synopsis>
751                         Show queue summary.
752                 </synopsis>
753                 <syntax>
754                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
755                         <parameter name="Queue" />
756                 </syntax>
757                 <description>
758                 </description>
759         </manager>
760         <manager name="QueueAdd" language="en_US">
761                 <synopsis>
762                         Add interface to queue.
763                 </synopsis>
764                 <syntax>
765                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
766                         <parameter name="Queue" required="true" />
767                         <parameter name="Interface" required="true" />
768                         <parameter name="Penalty" />
769                         <parameter name="Paused" />
770                         <parameter name="MemberName" />
771                         <parameter name="StateInterface" />
772                 </syntax>
773                 <description>
774                 </description>
775         </manager>
776         <manager name="QueueRemove" language="en_US">
777                 <synopsis>
778                         Remove interface from queue.
779                 </synopsis>
780                 <syntax>
781                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
782                         <parameter name="Queue" required="true" />
783                         <parameter name="Interface" required="true" />
784                 </syntax>
785                 <description>
786                 </description>
787         </manager>
788         <manager name="QueuePause" language="en_US">
789                 <synopsis>
790                         Makes a queue member temporarily unavailable.
791                 </synopsis>
792                 <syntax>
793                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
794                         <parameter name="Interface" required="true" />
795                         <parameter name="Paused" required="true" />
796                         <parameter name="Queue" />
797                         <parameter name="Reason" />
798                 </syntax>
799                 <description>
800                 </description>
801         </manager>
802         <manager name="QueueLog" language="en_US">
803                 <synopsis>
804                         Adds custom entry in queue_log.
805                 </synopsis>
806                 <syntax>
807                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
808                         <parameter name="Queue" required="true" />
809                         <parameter name="Event" required="true" />
810                         <parameter name="Uniqueid" />
811                         <parameter name="Interface" />
812                         <parameter name="Message" />
813                 </syntax>
814                 <description>
815                 </description>
816         </manager>
817         <manager name="QueuePenalty" language="en_US">
818                 <synopsis>
819                         Set the penalty for a queue member.
820                 </synopsis>
821                 <syntax>
822                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
823                         <parameter name="Interface" required="true" />
824                         <parameter name="Penalty" required="true" />
825                         <parameter name="Queue" />
826                 </syntax>
827                 <description>
828                 </description>
829         </manager>
830         <manager name="QueueMemberRingInUse" language="en_US">
831                 <synopsis>
832                         Set the ringinuse value for a queue member.
833                 </synopsis>
834                 <syntax>
835                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
836                         <parameter name="Interface" required="true" />
837                         <parameter name="RingInUse" required="true" />
838                         <parameter name="Queue" />
839                 </syntax>
840                 <description>
841                 </description>
842         </manager>
843         <manager name="QueueRule" language="en_US">
844                 <synopsis>
845                         Queue Rules.
846                 </synopsis>
847                 <syntax>
848                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
849                         <parameter name="Rule" />
850                 </syntax>
851                 <description>
852                 </description>
853         </manager>
854         <manager name="QueueReload" language="en_US">
855                 <synopsis>
856                         Reload a queue, queues, or any sub-section of a queue or queues.
857                 </synopsis>
858                 <syntax>
859                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
860                         <parameter name="Queue" />
861                         <parameter name="Members">
862                                 <enumlist>
863                                         <enum name="yes" />
864                                         <enum name="no" />
865                                 </enumlist>
866                         </parameter>
867                         <parameter name="Rules">
868                                 <enumlist>
869                                         <enum name="yes" />
870                                         <enum name="no" />
871                                 </enumlist>
872                         </parameter>
873                         <parameter name="Parameters">
874                                 <enumlist>
875                                         <enum name="yes" />
876                                         <enum name="no" />
877                                 </enumlist>
878                         </parameter>
879                 </syntax>
880                 <description>
881                 </description>
882         </manager>
883         <manager name="QueueReset" language="en_US">
884                 <synopsis>
885                         Reset queue statistics.
886                 </synopsis>
887                 <syntax>
888                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
889                         <parameter name="Queue" />
890                 </syntax>
891                 <description>
892                 </description>
893         </manager>
894
895         <managerEvent language="en_US" name="QueueMemberStatus">
896                 <managerEventInstance class="EVENT_FLAG_AGENT">
897                         <synopsis>Raised when a Queue member's status has changed.</synopsis>
898                         <syntax>
899                                 <parameter name="Queue">
900                                         <para>The name of the queue.</para>
901                                 </parameter>
902                                 <parameter name="MemberName">
903                                         <para>The name of the queue member.</para>
904                                 </parameter>
905                                 <parameter name="Interface">
906                                         <para>The queue member's channel technology or location.</para>
907                                 </parameter>
908                                 <parameter name="StateInterface">
909                                         <para>Channel technology or location from which to read device state changes.</para>
910                                 </parameter>
911                                 <parameter name="Membership">
912                                         <enumlist>
913                                                 <enum name="dynamic"/>
914                                                 <enum name="realtime"/>
915                                                 <enum name="static"/>
916                                         </enumlist>
917                                 </parameter>
918                                 <parameter name="Penalty">
919                                         <para>The penalty associated with the queue member.</para>
920                                 </parameter>
921                                 <parameter name="CallsTaken">
922                                         <para>The number of calls this queue member has serviced.</para>
923                                 </parameter>
924                                 <parameter name="LastCall">
925                                         <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
926                                 </parameter>
927                                 <parameter name="Status">
928                                         <para>The numeric device state status of the queue member.</para>
929                                         <enumlist>
930                                                 <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
931                                                 <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
932                                                 <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
933                                                 <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
934                                                 <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
935                                                 <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
936                                                 <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
937                                                 <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
938                                                 <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
939                                         </enumlist>
940                                 </parameter>
941                                 <parameter name="Paused">
942                                         <enumlist>
943                                                 <enum name="0"/>
944                                                 <enum name="1"/>
945                                         </enumlist>
946                                 </parameter>
947                                 <parameter name="Ringinuse">
948                                         <enumlist>
949                                                 <enum name="0"/>
950                                                 <enum name="1"/>
951                                         </enumlist>
952                                 </parameter>
953                         </syntax>
954                 </managerEventInstance>
955         </managerEvent>
956         <managerEvent language="en_US" name="QueueMemberAdded">
957                 <managerEventInstance class="EVENT_FLAG_AGENT">
958                         <synopsis>Raised when a member is added to the queue.</synopsis>
959                         <syntax>
960                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
961                         </syntax>
962                         <see-also>
963                                 <ref type="managerEvent">QueueMemberRemoved</ref>
964                                 <ref type="application">AddQueueMember</ref>
965                         </see-also>
966                 </managerEventInstance>
967         </managerEvent>
968         <managerEvent language="en_US" name="QueueMemberRemoved">
969                 <managerEventInstance class="EVENT_FLAG_AGENT">
970                         <synopsis>Raised when a member is removed from the queue.</synopsis>
971                         <syntax>
972                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
973                         </syntax>
974                         <see-also>
975                                 <ref type="managerEvent">QueueMemberAdded</ref>
976                                 <ref type="application">RemoveQueueMember</ref>
977                         </see-also>
978                 </managerEventInstance>
979         </managerEvent>
980         <managerEvent language="en_US" name="QueueMemberPaused">
981                 <managerEventInstance class="EVENT_FLAG_AGENT">
982                         <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
983                         <syntax>
984                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
985                                 <parameter name="Reason">
986                                         <para>The reason a member was paused.</para>
987                                 </parameter>
988                         </syntax>
989                         <see-also>
990                                 <ref type="application">PauseQueueMember</ref>
991                                 <ref type="application">UnPauseQueueMember</ref>
992                         </see-also>
993                 </managerEventInstance>
994         </managerEvent>
995         <managerEvent language="en_US" name="QueueMemberPenalty">
996                 <managerEventInstance class="EVENT_FLAG_AGENT">
997                         <synopsis>Raised when a member's penalty is changed.</synopsis>
998                         <syntax>
999                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1000                         </syntax>
1001                         <see-also>
1002                                 <ref type="function">QUEUE_MEMBER</ref>
1003                         </see-also>
1004                 </managerEventInstance>
1005         </managerEvent>
1006         <managerEvent language="en_US" name="QueueMemberRinginuse">
1007                 <managerEventInstance class="EVENT_FLAG_AGENT">
1008                         <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
1009                         <syntax>
1010                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1011                         </syntax>
1012                         <see-also>
1013                                 <ref type="function">QUEUE_MEMBER</ref>
1014                         </see-also>
1015                 </managerEventInstance>
1016         </managerEvent>
1017         <managerEvent language="en_US" name="QueueCallerJoin">
1018                 <managerEventInstance class="EVENT_FLAG_AGENT">
1019                         <synopsis>Raised when a caller joins a Queue.</synopsis>
1020                         <syntax>
1021                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1022                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1023                                 <parameter name="Position">
1024                                         <para>This channel's current position in the queue.</para>
1025                                 </parameter>
1026                                 <parameter name="Count">
1027                                         <para>The total number of channels in the queue.</para>
1028                                 </parameter>
1029                         </syntax>
1030                         <see-also>
1031                                 <ref type="managerEvent">QueueCallerLeave</ref>
1032                                 <ref type="application">Queue</ref>
1033                         </see-also>
1034                 </managerEventInstance>
1035         </managerEvent>
1036         <managerEvent language="en_US" name="QueueCallerLeave">
1037                 <managerEventInstance class="EVENT_FLAG_AGENT">
1038                         <synopsis>Raised when a caller leaves a Queue.</synopsis>
1039                         <syntax>
1040                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1041                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1042                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
1043                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1044                         </syntax>
1045                         <see-also>
1046                                 <ref type="managerEvent">QueueCallerJoin</ref>
1047                         </see-also>
1048                 </managerEventInstance>
1049         </managerEvent>
1050         <managerEvent language="en_US" name="QueueCallerAbandon">
1051                 <managerEventInstance class="EVENT_FLAG_AGENT">
1052                         <synopsis>Raised when a caller abandons the queue.</synopsis>
1053                         <syntax>
1054                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1055                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1056                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1057                                 <parameter name="OriginalPosition">
1058                                         <para>The channel's original position in the queue.</para>
1059                                 </parameter>
1060                                 <parameter name="HoldTime">
1061                                         <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1062                                 </parameter>
1063                         </syntax>
1064                 </managerEventInstance>
1065         </managerEvent>
1066         <managerEvent language="en_US" name="AgentCalled">
1067                 <managerEventInstance class="EVENT_FLAG_AGENT">
1068                         <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
1069                         <syntax>
1070                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1071                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
1072                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1073                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1074                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1075                         </syntax>
1076                         <see-also>
1077                                 <ref type="managerEvent">AgentRingNoAnswer</ref>
1078                                 <ref type="managerEvent">AgentComplete</ref>
1079                                 <ref type="managerEvent">AgentConnect</ref>
1080                         </see-also>
1081                 </managerEventInstance>
1082         </managerEvent>
1083         <managerEvent language="en_US" name="AgentRingNoAnswer">
1084                 <managerEventInstance class="EVENT_FLAG_AGENT">
1085                         <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
1086                         <syntax>
1087                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1088                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
1089                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1090                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1091                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1092                                 <parameter name="RingTime">
1093                                         <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1094                                 </parameter>
1095                         </syntax>
1096                         <see-also>
1097                                 <ref type="managerEvent">AgentCalled</ref>
1098                         </see-also>
1099                 </managerEventInstance>
1100         </managerEvent>
1101         <managerEvent language="en_US" name="AgentComplete">
1102                 <managerEventInstance class="EVENT_FLAG_AGENT">
1103                         <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
1104                         <syntax>
1105                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1106                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
1107                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1108                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1109                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1110                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1111                                 <parameter name="TalkTime">
1112                                         <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1113                                 </parameter>
1114                                 <parameter name="Reason">
1115                                         <enumlist>
1116                                                 <enum name="caller"/>
1117                                                 <enum name="agent"/>
1118                                                 <enum name="transfer"/>
1119                                         </enumlist>
1120                                 </parameter>
1121                         </syntax>
1122                         <see-also>
1123                                 <ref type="managerEvent">AgentCalled</ref>
1124                                 <ref type="managerEvent">AgentConnect</ref>
1125                         </see-also>
1126                 </managerEventInstance>
1127         </managerEvent>
1128         <managerEvent language="en_US" name="AgentDump">
1129                 <managerEventInstance class="EVENT_FLAG_AGENT">
1130                         <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
1131                         <syntax>
1132                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1133                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
1134                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1135                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1136                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1137                         </syntax>
1138                         <see-also>
1139                                 <ref type="managerEvent">AgentCalled</ref>
1140                                 <ref type="managerEvent">AgentConnect</ref>
1141                         </see-also>
1142                 </managerEventInstance>
1143         </managerEvent>
1144         <managerEvent language="en_US" name="AgentConnect">
1145                 <managerEventInstance class="EVENT_FLAG_AGENT">
1146                         <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
1147                         <syntax>
1148                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
1149                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
1150                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1151                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1152                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1153                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
1154                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1155                         </syntax>
1156                         <see-also>
1157                                 <ref type="managerEvent">AgentCalled</ref>
1158                                 <ref type="managerEvent">AgentComplete</ref>
1159                                 <ref type="managerEvent">AgentDump</ref>
1160                         </see-also>
1161                 </managerEventInstance>
1162         </managerEvent>
1163  ***/
1164
1165 enum {
1166         OPT_MARK_AS_ANSWERED =       (1 << 0),
1167         OPT_GO_ON =                  (1 << 1),
1168         OPT_DATA_QUALITY =           (1 << 2),
1169         OPT_CALLEE_GO_ON =           (1 << 3),
1170         OPT_CALLEE_HANGUP =          (1 << 4),
1171         OPT_CALLER_HANGUP =          (1 << 5),
1172         OPT_IGNORE_CALL_FW =         (1 << 6),
1173         OPT_IGNORE_CONNECTEDLINE =   (1 << 7),
1174         OPT_CALLEE_PARK =            (1 << 8),
1175         OPT_CALLER_PARK =            (1 << 9),
1176         OPT_NO_RETRY =               (1 << 10),
1177         OPT_RINGING =                (1 << 11),
1178         OPT_RING_WHEN_RINGING =      (1 << 12),
1179         OPT_CALLEE_TRANSFER =        (1 << 13),
1180         OPT_CALLER_TRANSFER =        (1 << 14),
1181         OPT_CALLEE_AUTOMIXMON =      (1 << 15),
1182         OPT_CALLER_AUTOMIXMON =      (1 << 16),
1183         OPT_CALLEE_AUTOMON =         (1 << 17),
1184         OPT_CALLER_AUTOMON =         (1 << 18),
1185 };
1186
1187 enum {
1188         OPT_ARG_CALLEE_GO_ON = 0,
1189         /* note: this entry _MUST_ be the last one in the enum */
1190         OPT_ARG_ARRAY_SIZE
1191 };
1192
1193 AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
1194         AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
1195         AST_APP_OPTION('c', OPT_GO_ON),
1196         AST_APP_OPTION('d', OPT_DATA_QUALITY),
1197         AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
1198         AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
1199         AST_APP_OPTION('H', OPT_CALLER_HANGUP),
1200         AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
1201         AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
1202         AST_APP_OPTION('k', OPT_CALLEE_PARK),
1203         AST_APP_OPTION('K', OPT_CALLER_PARK),
1204         AST_APP_OPTION('n', OPT_NO_RETRY),
1205         AST_APP_OPTION('r', OPT_RINGING),
1206         AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
1207         AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1208         AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
1209         AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
1210         AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
1211         AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
1212         AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
1213 END_OPTIONS);
1214
1215 enum {
1216         QUEUE_STRATEGY_RINGALL = 0,
1217         QUEUE_STRATEGY_LEASTRECENT,
1218         QUEUE_STRATEGY_FEWESTCALLS,
1219         QUEUE_STRATEGY_RANDOM,
1220         QUEUE_STRATEGY_RRMEMORY,
1221         QUEUE_STRATEGY_LINEAR,
1222         QUEUE_STRATEGY_WRANDOM,
1223         QUEUE_STRATEGY_RRORDERED,
1224 };
1225
1226 enum {
1227      QUEUE_AUTOPAUSE_OFF = 0,
1228      QUEUE_AUTOPAUSE_ON,
1229      QUEUE_AUTOPAUSE_ALL
1230 };
1231
1232 enum queue_reload_mask {
1233         QUEUE_RELOAD_PARAMETERS = (1 << 0),
1234         QUEUE_RELOAD_MEMBER = (1 << 1),
1235         QUEUE_RELOAD_RULES = (1 << 2),
1236         QUEUE_RESET_STATS = (1 << 3),
1237 };
1238
1239 static const struct strategy {
1240         int strategy;
1241         const char *name;
1242 } strategies[] = {
1243         { QUEUE_STRATEGY_RINGALL, "ringall" },
1244         { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
1245         { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
1246         { QUEUE_STRATEGY_RANDOM, "random" },
1247         { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
1248         { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
1249         { QUEUE_STRATEGY_LINEAR, "linear" },
1250         { QUEUE_STRATEGY_WRANDOM, "wrandom"},
1251         { QUEUE_STRATEGY_RRORDERED, "rrordered"},
1252 };
1253
1254 static const struct autopause {
1255         int autopause;
1256         const char *name;
1257 } autopausesmodes [] = {
1258         { QUEUE_AUTOPAUSE_OFF,"no" },
1259         { QUEUE_AUTOPAUSE_ON, "yes" },
1260         { QUEUE_AUTOPAUSE_ALL,"all" },
1261 };
1262
1263 #define DEFAULT_RETRY           5
1264 #define DEFAULT_TIMEOUT         15
1265 #define RECHECK                 1               /*!< Recheck every second to see we we're at the top yet */
1266 #define MAX_PERIODIC_ANNOUNCEMENTS 10           /*!< The maximum periodic announcements we can have */
1267 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15       /*!< The minimum number of seconds between position announcements \
1268                                                      The default value of 15 provides backwards compatibility */
1269 #define MAX_QUEUE_BUCKETS 53
1270
1271 #define RES_OKAY        0               /*!< Action completed */
1272 #define RES_EXISTS      (-1)            /*!< Entry already exists */
1273 #define RES_OUTOFMEMORY (-2)            /*!< Out of memory */
1274 #define RES_NOSUCHQUEUE (-3)            /*!< No such queue */
1275 #define RES_NOT_DYNAMIC (-4)            /*!< Member is not dynamic */
1276
1277 static char *app = "Queue";
1278
1279 static char *app_aqm = "AddQueueMember" ;
1280
1281 static char *app_rqm = "RemoveQueueMember" ;
1282
1283 static char *app_pqm = "PauseQueueMember" ;
1284
1285 static char *app_upqm = "UnpauseQueueMember" ;
1286
1287 static char *app_ql = "QueueLog" ;
1288
1289 /*! \brief Persistent Members astdb family */
1290 static const char * const pm_family = "Queue/PersistentMembers";
1291
1292 /*! \brief queues.conf [general] option */
1293 static int queue_persistent_members = 0;
1294
1295 /*! \brief queues.conf per-queue weight option */
1296 static int use_weight = 0;
1297
1298 /*! \brief queues.conf [general] option */
1299 static int autofill_default = 1;
1300
1301 /*! \brief queues.conf [general] option */
1302 static int montype_default = 0;
1303
1304 /*! \brief queues.conf [general] option */
1305 static int shared_lastcall = 1;
1306
1307 /*! \brief Subscription to device state change messages */
1308 static struct stasis_subscription *device_state_sub;
1309
1310 /*! \brief queues.conf [general] option */
1311 static int update_cdr = 0;
1312
1313 /*! \brief queues.conf [general] option */
1314 static int negative_penalty_invalid = 0;
1315
1316 /*! \brief queues.conf [general] option */
1317 static int log_membername_as_agent = 0;
1318
1319 /*! \brief name of the ringinuse field in the realtime database */
1320 static char *realtime_ringinuse_field;
1321
1322 enum queue_result {
1323         QUEUE_UNKNOWN = 0,
1324         QUEUE_TIMEOUT = 1,
1325         QUEUE_JOINEMPTY = 2,
1326         QUEUE_LEAVEEMPTY = 3,
1327         QUEUE_JOINUNAVAIL = 4,
1328         QUEUE_LEAVEUNAVAIL = 5,
1329         QUEUE_FULL = 6,
1330         QUEUE_CONTINUE = 7,
1331 };
1332
1333 static const struct {
1334         enum queue_result id;
1335         char *text;
1336 } queue_results[] = {
1337         { QUEUE_UNKNOWN, "UNKNOWN" },
1338         { QUEUE_TIMEOUT, "TIMEOUT" },
1339         { QUEUE_JOINEMPTY,"JOINEMPTY" },
1340         { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
1341         { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
1342         { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
1343         { QUEUE_FULL, "FULL" },
1344         { QUEUE_CONTINUE, "CONTINUE" },
1345 };
1346
1347 enum queue_timeout_priority {
1348         TIMEOUT_PRIORITY_APP,
1349         TIMEOUT_PRIORITY_CONF,
1350 };
1351
1352 /*! \brief We define a custom "local user" structure because we
1353  *  use it not only for keeping track of what is in use but
1354  *  also for keeping track of who we're dialing.
1355  *
1356  *  There are two "links" defined in this structure, q_next and call_next.
1357  *  q_next links ALL defined callattempt structures into a linked list. call_next is
1358  *  a link which allows for a subset of the callattempts to be traversed. This subset
1359  *  is used in wait_for_answer so that irrelevant callattempts are not traversed. This
1360  *  also is helpful so that queue logs are always accurate in the case where a call to
1361  *  a member times out, especially if using the ringall strategy.
1362 */
1363
1364 struct callattempt {
1365         struct callattempt *q_next;
1366         struct callattempt *call_next;
1367         struct ast_channel *chan;
1368         char interface[256];                    /*!< An Asterisk dial string (not a channel name) */
1369         int metric;
1370         time_t lastcall;
1371         struct call_queue *lastqueue;
1372         struct member *member;
1373         /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
1374         struct ast_party_connected_line connected;
1375         /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
1376         unsigned int pending_connected_update:1;
1377         /*! TRUE if the connected line update is blocked. */
1378         unsigned int block_connected_update:1;
1379         /*! TRUE if caller id is not available for connected line */
1380         unsigned int dial_callerid_absent:1;
1381         /*! TRUE if the call is still active */
1382         unsigned int stillgoing:1;
1383         struct ast_aoc_decoded *aoc_s_rate_list;
1384 };
1385
1386
1387 struct queue_ent {
1388         struct call_queue *parent;             /*!< What queue is our parent */
1389         char moh[MAX_MUSICCLASS];              /*!< Name of musiconhold to be used */
1390         char announce[PATH_MAX];               /*!< Announcement to play for member when call is answered */
1391         char context[AST_MAX_CONTEXT];         /*!< Context when user exits queue */
1392         char digits[AST_MAX_EXTENSION];        /*!< Digits entered while in queue */
1393         int valid_digits;                      /*!< Digits entered correspond to valid extension. Exited */
1394         int pos;                               /*!< Where we are in the queue */
1395         int prio;                              /*!< Our priority */
1396         int last_pos_said;                     /*!< Last position we told the user */
1397         int ring_when_ringing;                 /*!< Should we only use ring indication when a channel is ringing? */
1398         time_t last_periodic_announce_time;    /*!< The last time we played a periodic announcement */
1399         int last_periodic_announce_sound;      /*!< The last periodic announcement we made */
1400         time_t last_pos;                       /*!< Last time we told the user their position */
1401         int opos;                              /*!< Where we started in the queue */
1402         int handled;                           /*!< Whether our call was handled */
1403         int pending;                           /*!< Non-zero if we are attempting to call a member */
1404         int max_penalty;                       /*!< Limit the members that can take this call to this penalty or lower */
1405         int min_penalty;                       /*!< Limit the members that can take this call to this penalty or higher */
1406         int linpos;                            /*!< If using linear strategy, what position are we at? */
1407         int linwrapped;                        /*!< Is the linpos wrapped? */
1408         time_t start;                          /*!< When we started holding */
1409         time_t expire;                         /*!< When this entry should expire (time out of queue) */
1410         int cancel_answered_elsewhere;         /*!< Whether we should force the CAE flag on this call (C) option*/
1411         struct ast_channel *chan;              /*!< Our channel */
1412         AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
1413         struct penalty_rule *pr;               /*!< Pointer to the next penalty rule to implement */
1414         struct queue_ent *next;                /*!< The next queue entry */
1415 };
1416
1417 struct member {
1418         char interface[AST_CHANNEL_NAME];    /*!< Technology/Location to dial to reach this member*/
1419         char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
1420         char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
1421         char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
1422         char membername[80];                 /*!< Member name to use in queue logs */
1423         int penalty;                         /*!< Are we a last resort? */
1424         int calls;                           /*!< Number of calls serviced by this member */
1425         int dynamic;                         /*!< Are we dynamically added? */
1426         int realtime;                        /*!< Is this member realtime? */
1427         int status;                          /*!< Status of queue member */
1428         int paused;                          /*!< Are we paused (not accepting calls)? */
1429         int queuepos;                        /*!< In what order (pertains to certain strategies) should this member be called? */
1430         time_t lastcall;                     /*!< When last successful call was hungup */
1431         struct call_queue *lastqueue;        /*!< Last queue we received a call */
1432         unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
1433         unsigned int delme:1;                /*!< Flag to delete entry on reload */
1434         unsigned int call_pending:1;         /*!< TRUE if the Q is attempting to place a call to the member. */
1435         char rt_uniqueid[80];                /*!< Unique id of realtime member entry */
1436         unsigned int ringinuse:1;            /*!< Flag to ring queue members even if their status is 'inuse' */
1437 };
1438
1439 enum empty_conditions {
1440         QUEUE_EMPTY_PENALTY = (1 << 0),
1441         QUEUE_EMPTY_PAUSED = (1 << 1),
1442         QUEUE_EMPTY_INUSE = (1 << 2),
1443         QUEUE_EMPTY_RINGING = (1 << 3),
1444         QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
1445         QUEUE_EMPTY_INVALID = (1 << 5),
1446         QUEUE_EMPTY_UNKNOWN = (1 << 6),
1447         QUEUE_EMPTY_WRAPUP = (1 << 7),
1448 };
1449
1450 enum member_properties {
1451         MEMBER_PENALTY = 0,
1452         MEMBER_RINGINUSE = 1,
1453 };
1454
1455 /* values used in multi-bit flags in call_queue */
1456 #define ANNOUNCEHOLDTIME_ALWAYS 1
1457 #define ANNOUNCEHOLDTIME_ONCE 2
1458 #define QUEUE_EVENT_VARIABLES 3
1459
1460 struct penalty_rule {
1461         int time;                           /*!< Number of seconds that need to pass before applying this rule */
1462         int max_value;                      /*!< The amount specified in the penalty rule for max penalty */
1463         int min_value;                      /*!< The amount specified in the penalty rule for min penalty */
1464         int max_relative;                   /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
1465         int min_relative;                   /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
1466         AST_LIST_ENTRY(penalty_rule) list;  /*!< Next penalty_rule */
1467 };
1468
1469 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
1470 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
1471 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
1472 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
1473
1474 struct call_queue {
1475         AST_DECLARE_STRING_FIELDS(
1476                 /*! Queue name */
1477                 AST_STRING_FIELD(name);
1478                 /*! Music on Hold class */
1479                 AST_STRING_FIELD(moh);
1480                 /*! Announcement to play when call is answered */
1481                 AST_STRING_FIELD(announce);
1482                 /*! Exit context */
1483                 AST_STRING_FIELD(context);
1484                 /*! Macro to run upon member connection */
1485                 AST_STRING_FIELD(membermacro);
1486                 /*! Gosub to run upon member connection */
1487                 AST_STRING_FIELD(membergosub);
1488                 /*! Default rule to use if none specified in call to Queue() */
1489                 AST_STRING_FIELD(defaultrule);
1490                 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
1491                 AST_STRING_FIELD(sound_next);
1492                 /*! Sound file: "There are currently" (def. queue-thereare) */
1493                 AST_STRING_FIELD(sound_thereare);
1494                 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
1495                 AST_STRING_FIELD(sound_calls);
1496                 /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
1497                 AST_STRING_FIELD(queue_quantity1);
1498                 /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
1499                 AST_STRING_FIELD(queue_quantity2);
1500                 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
1501                 AST_STRING_FIELD(sound_holdtime);
1502                 /*! Sound file: "minutes." (def. queue-minutes) */
1503                 AST_STRING_FIELD(sound_minutes);
1504                 /*! Sound file: "minute." (def. queue-minute) */
1505                 AST_STRING_FIELD(sound_minute);
1506                 /*! Sound file: "seconds." (def. queue-seconds) */
1507                 AST_STRING_FIELD(sound_seconds);
1508                 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
1509                 AST_STRING_FIELD(sound_thanks);
1510                 /*! Sound file: Custom announce for caller, no default */
1511                 AST_STRING_FIELD(sound_callerannounce);
1512                 /*! Sound file: "Hold time" (def. queue-reporthold) */
1513                 AST_STRING_FIELD(sound_reporthold);
1514         );
1515         /*! Sound files: Custom announce, no default */
1516         struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
1517         unsigned int dead:1;
1518         unsigned int ringinuse:1;
1519         unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
1520         unsigned int setinterfacevar:1;
1521         unsigned int setqueuevar:1;
1522         unsigned int setqueueentryvar:1;
1523         unsigned int reportholdtime:1;
1524         unsigned int wrapped:1;
1525         unsigned int timeoutrestart:1;
1526         unsigned int announceholdtime:2;
1527         unsigned int announceposition:3;
1528         int strategy:4;
1529         unsigned int realtime:1;
1530         unsigned int found:1;
1531         unsigned int relativeperiodicannounce:1;
1532         unsigned int autopausebusy:1;
1533         unsigned int autopauseunavail:1;
1534         enum empty_conditions joinempty;
1535         enum empty_conditions leavewhenempty;
1536         int announcepositionlimit;          /*!< How many positions we announce? */
1537         int announcefrequency;              /*!< How often to announce their position */
1538         int minannouncefrequency;           /*!< The minimum number of seconds between position announcements (def. 15) */
1539         int periodicannouncefrequency;      /*!< How often to play periodic announcement */
1540         int numperiodicannounce;            /*!< The number of periodic announcements configured */
1541         int randomperiodicannounce;         /*!< Are periodic announcments randomly chosen */
1542         int roundingseconds;                /*!< How many seconds do we round to? */
1543         int holdtime;                       /*!< Current avg holdtime, based on an exponential average */
1544         int talktime;                       /*!< Current avg talktime, based on the same exponential average */
1545         int callscompleted;                 /*!< Number of queue calls completed */
1546         int callsabandoned;                 /*!< Number of queue calls abandoned */
1547         int servicelevel;                   /*!< seconds setting for servicelevel*/
1548         int callscompletedinsl;             /*!< Number of calls answered with servicelevel*/
1549         char monfmt[8];                     /*!< Format to use when recording calls */
1550         int montype;                        /*!< Monitor type  Monitor vs. MixMonitor */
1551         int count;                          /*!< How many entries */
1552         int maxlen;                         /*!< Max number of entries */
1553         int wrapuptime;                     /*!< Wrapup Time */
1554         int penaltymemberslimit;            /*!< Disregard penalty when queue has fewer than this many members */
1555
1556         int retry;                          /*!< Retry calling everyone after this amount of time */
1557         int timeout;                        /*!< How long to wait for an answer */
1558         int weight;                         /*!< Respective weight */
1559         int autopause;                      /*!< Auto pause queue members if they fail to answer */
1560         int autopausedelay;                 /*!< Delay auto pause for autopausedelay seconds since last call */
1561         int timeoutpriority;                /*!< Do we allow a fraction of the timeout to occur for a ring? */
1562
1563         /* Queue strategy things */
1564         int rrpos;                          /*!< Round Robin - position */
1565         int memberdelay;                    /*!< Seconds to delay connecting member to caller */
1566         int autofill;                       /*!< Ignore the head call status and ring an available agent */
1567
1568         struct ao2_container *members;             /*!< Head of the list of members */
1569         struct queue_ent *head;             /*!< Head of the list of callers */
1570         AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
1571         AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
1572 };
1573
1574 struct rule_list {
1575         char name[80];
1576         AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
1577         AST_LIST_ENTRY(rule_list) list;
1578 };
1579
1580 static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
1581
1582 static struct ao2_container *queues;
1583
1584 static void update_realtime_members(struct call_queue *q);
1585 static struct member *interface_exists(struct call_queue *q, const char *interface);
1586 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
1587
1588 #if 0   // BUGBUG
1589 static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
1590 #endif  // BUGBUG
1591
1592 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
1593 /*! \brief sets the QUEUESTATUS channel variable */
1594 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
1595 {
1596         int i;
1597
1598         for (i = 0; i < ARRAY_LEN(queue_results); i++) {
1599                 if (queue_results[i].id == res) {
1600                         pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
1601                         return;
1602                 }
1603         }
1604 }
1605
1606 static const char *int2strat(int strategy)
1607 {
1608         int x;
1609
1610         for (x = 0; x < ARRAY_LEN(strategies); x++) {
1611                 if (strategy == strategies[x].strategy) {
1612                         return strategies[x].name;
1613                 }
1614         }
1615
1616         return "<unknown>";
1617 }
1618
1619 static int strat2int(const char *strategy)
1620 {
1621         int x;
1622
1623         for (x = 0; x < ARRAY_LEN(strategies); x++) {
1624                 if (!strcasecmp(strategy, strategies[x].name)) {
1625                         return strategies[x].strategy;
1626                 }
1627         }
1628
1629         return -1;
1630 }
1631
1632 static int autopause2int(const char *autopause)
1633 {
1634         int x;
1635         /*This 'double check' that default value is OFF */
1636         if (ast_strlen_zero(autopause)) {
1637                 return QUEUE_AUTOPAUSE_OFF;
1638         }
1639
1640         /*This 'double check' is to ensure old values works */
1641         if(ast_true(autopause)) {
1642                 return QUEUE_AUTOPAUSE_ON;
1643         }
1644
1645         for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1646                 if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1647                         return autopausesmodes[x].autopause;
1648                 }
1649         }
1650
1651         /*This 'double check' that default value is OFF */
1652         return QUEUE_AUTOPAUSE_OFF;
1653 }
1654
1655 static int queue_hash_cb(const void *obj, const int flags)
1656 {
1657         const struct call_queue *q = obj;
1658
1659         return ast_str_case_hash(q->name);
1660 }
1661
1662 static int queue_cmp_cb(void *obj, void *arg, int flags)
1663 {
1664         struct call_queue *q = obj, *q2 = arg;
1665         return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1666 }
1667
1668 /*! \internal
1669  * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
1670  * \param obj the member being acted on
1671  * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
1672  */
1673 static int queue_member_decrement_followers(void *obj, void *arg, int flag)
1674 {
1675         struct member *mem = obj;
1676         int *decrement_followers_after = arg;
1677
1678         if (mem->queuepos > *decrement_followers_after) {
1679                 mem->queuepos--;
1680         }
1681
1682         return 0;
1683 }
1684
1685 /*! \internal
1686  * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
1687  *        on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
1688  * \param obj member being acted on
1689  * \param arg pointer to the queue members are being removed from
1690  */
1691 static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
1692 {
1693         struct member *mem = obj;
1694         struct call_queue *queue = arg;
1695         int rrpos = mem->queuepos;
1696
1697         if (mem->delme) {
1698                 ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &rrpos);
1699         }
1700
1701         return 0;
1702 }
1703
1704 /*! \internal
1705  * \brief Use this to decrement followers during removal of a member
1706  * \param queue which queue the member is being removed from
1707  * \param mem which member is being removed from the queue
1708  */
1709 static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
1710 {
1711         int pos = mem->queuepos;
1712
1713         /* If the position being removed is less than the current place in the queue, reduce the queue position by one so that we don't skip the member
1714          * who would have been next otherwise. */
1715         if (pos < queue->rrpos) {
1716                 queue->rrpos--;
1717         }
1718
1719         ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
1720 }
1721
1722 #ifdef REF_DEBUG_ONLY_QUEUES
1723 #define queue_ref(q)                            _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
1724 #define queue_unref(q)                          _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
1725 #define queue_t_ref(q, tag)                     _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1726 #define queue_t_unref(q, tag)           _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1727 #define queues_t_link(c, q, tag)        __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1728 #define queues_t_unlink(c, q, tag)      __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1729
1730 static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
1731 {
1732         __ao2_ref_debug(q, 1, tag, file, line, filename);
1733         return q;
1734 }
1735
1736 static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
1737 {
1738         __ao2_ref_debug(q, -1, tag, file, line, filename);
1739         return NULL;
1740 }
1741
1742 #else
1743
1744 #define queue_t_ref(q, tag)                     queue_ref(q)
1745 #define queue_t_unref(q, tag)           queue_unref(q)
1746 #define queues_t_link(c, q, tag)        ao2_t_link(c, q, tag)
1747 #define queues_t_unlink(c, q, tag)      ao2_t_unlink(c, q, tag)
1748
1749 static inline struct call_queue *queue_ref(struct call_queue *q)
1750 {
1751         ao2_ref(q, 1);
1752         return q;
1753 }
1754
1755 static inline struct call_queue *queue_unref(struct call_queue *q)
1756 {
1757         ao2_ref(q, -1);
1758         return NULL;
1759 }
1760 #endif
1761
1762 /*! \brief Set variables of queue */
1763 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
1764 {
1765         char interfacevar[256]="";
1766         float sl = 0;
1767
1768         ao2_lock(q);
1769
1770         if (q->setqueuevar) {
1771                 sl = 0;
1772                 if (q->callscompleted > 0) {
1773                         sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
1774                 }
1775
1776                 snprintf(interfacevar, sizeof(interfacevar),
1777                         "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1778                         q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned,  q->servicelevel, sl);
1779
1780                 ao2_unlock(q);
1781
1782                 pbx_builtin_setvar_multiple(chan, interfacevar);
1783         } else {
1784                 ao2_unlock(q);
1785         }
1786 }
1787
1788 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
1789 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
1790 {
1791         struct queue_ent *cur;
1792
1793         if (!q || !new)
1794                 return;
1795         if (prev) {
1796                 cur = prev->next;
1797                 prev->next = new;
1798         } else {
1799                 cur = q->head;
1800                 q->head = new;
1801         }
1802         new->next = cur;
1803
1804         /* every queue_ent must have a reference to it's parent call_queue, this
1805          * reference does not go away until the end of the queue_ent's life, meaning
1806          * that even when the queue_ent leaves the call_queue this ref must remain. */
1807         queue_ref(q);
1808         new->parent = q;
1809         new->pos = ++(*pos);
1810         new->opos = *pos;
1811 }
1812
1813 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_join_type);
1814 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_leave_type);
1815 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_abandon_type);
1816
1817 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_status_type);
1818 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_added_type);
1819 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_removed_type);
1820 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_pause_type);
1821 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_penalty_type);
1822 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_ringinuse_type);
1823
1824 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_called_type);
1825 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_connect_type);
1826 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_complete_type);
1827 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_dump_type);
1828 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_ringnoanswer_type);
1829
1830 static void queue_channel_manager_event(void *data,
1831         struct stasis_subscription *sub, struct stasis_topic *topic,
1832         struct stasis_message *message)
1833 {
1834         const char *type = data;
1835         struct ast_channel_blob *obj = stasis_message_data(message);
1836         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1837         RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1838
1839         channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1840         if (!channel_event_string) {
1841                 return;
1842         }
1843
1844         event_string = ast_manager_str_from_json_object(obj->blob, NULL);
1845         if (!event_string) {
1846                 return;
1847         }
1848
1849         manager_event(EVENT_FLAG_AGENT, type,
1850                 "%s"
1851                 "%s",
1852                 ast_str_buffer(channel_event_string),
1853                 ast_str_buffer(event_string));
1854 }
1855
1856 static void queue_multi_channel_manager_event(void *data,
1857         struct stasis_subscription *sub, struct stasis_topic *topic,
1858         struct stasis_message *message)
1859 {
1860         const char *type = data;
1861         struct ast_multi_channel_blob *obj = stasis_message_data(message);
1862         struct ast_channel_snapshot *caller;
1863         struct ast_channel_snapshot *agent;
1864         RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
1865         RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
1866         RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1867
1868         caller = ast_multi_channel_blob_get_channel(obj, "caller");
1869         agent = ast_multi_channel_blob_get_channel(obj, "agent");
1870
1871         caller_event_string = ast_manager_build_channel_state_string(caller);
1872         agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
1873
1874         if (!caller_event_string || !agent_event_string) {
1875                 return;
1876         }
1877
1878         event_string = ast_manager_str_from_json_object(ast_multi_channel_blob_get_json(obj), NULL);
1879         if (!event_string) {
1880                 return;
1881         }
1882
1883         manager_event(EVENT_FLAG_AGENT, type,
1884                 "%s"
1885                 "%s"
1886                 "%s",
1887                 ast_str_buffer(caller_event_string),
1888                 ast_str_buffer(agent_event_string),
1889                 ast_str_buffer(event_string));
1890 }
1891
1892 static void queue_member_manager_event(void *data,
1893         struct stasis_subscription *sub, struct stasis_topic *topic,
1894         struct stasis_message *message)
1895 {
1896         const char *type = data;
1897         struct ast_json_payload *payload = stasis_message_data(message);
1898         struct ast_json *event = payload->json;
1899         RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1900
1901         event_string = ast_manager_str_from_json_object(event, NULL);
1902         if (!event_string) {
1903                 return;
1904         }
1905
1906         manager_event(EVENT_FLAG_AGENT, type,
1907                 "%s", ast_str_buffer(event_string));
1908 }
1909
1910 static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent, struct stasis_message_type *type, struct ast_json *blob)
1911 {
1912         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
1913         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1914         struct ast_channel_snapshot *caller_snapshot;
1915         struct ast_channel_snapshot *agent_snapshot;
1916
1917         payload = ast_multi_channel_blob_create(blob);
1918         if (!payload) {
1919                 return;
1920         }
1921
1922         caller_snapshot = ast_channel_snapshot_create(caller);
1923         agent_snapshot = ast_channel_snapshot_create(agent);
1924
1925         if (!caller_snapshot || !agent_snapshot) {
1926                 return;
1927         }
1928
1929         ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
1930         ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
1931
1932         msg = stasis_message_create(type, payload);
1933         if (!msg) {
1934                 return;
1935         }
1936
1937         stasis_publish(ast_channel_topic(caller), msg);
1938 }
1939
1940 static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
1941 {
1942         RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
1943         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1944
1945         payload = ast_json_payload_create(blob);
1946         if (!payload) {
1947                 return;
1948         }
1949
1950         msg = stasis_message_create(type, payload);
1951         if (!msg) {
1952                 return;
1953         }
1954
1955         stasis_publish(ast_manager_get_topic(), msg);
1956 }
1957
1958 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
1959 {
1960         return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i}",
1961                 "Queue", q->name,
1962                 "MemberName", mem->membername,
1963                 "Interface", mem->interface,
1964                 "StateInterface", mem->state_interface,
1965                 "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
1966                 "Penalty", mem->penalty,
1967                 "CallsTaken", mem->calls,
1968                 "LastCall", (int)mem->lastcall,
1969                 "Status", mem->status,
1970                 "Paused", mem->paused,
1971                 "Ringinuse", mem->ringinuse);
1972 }
1973
1974 /*! \brief Check if members are available
1975  *
1976  * This function checks to see if members are available to be called. If any member
1977  * is available, the function immediately returns 0. If no members are available,
1978  * then -1 is returned.
1979  */
1980 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions)
1981 {
1982         struct member *member;
1983         struct ao2_iterator mem_iter;
1984
1985         ao2_lock(q);
1986         mem_iter = ao2_iterator_init(q->members, 0);
1987         for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
1988                 if ((max_penalty && (member->penalty > max_penalty)) || (min_penalty && (member->penalty < min_penalty))) {
1989                         if (conditions & QUEUE_EMPTY_PENALTY) {
1990                                 ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
1991                                 continue;
1992                         }
1993                 }
1994
1995                 switch (member->status) {
1996                 case AST_DEVICE_INVALID:
1997                         if (conditions & QUEUE_EMPTY_INVALID) {
1998                                 ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
1999                                 break;
2000                         }
2001                         goto default_case;
2002                 case AST_DEVICE_UNAVAILABLE:
2003                         if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
2004                                 ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
2005                                 break;
2006                         }
2007                         goto default_case;
2008                 case AST_DEVICE_INUSE:
2009                         if (conditions & QUEUE_EMPTY_INUSE) {
2010                                 ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
2011                                 break;
2012                         }
2013                         goto default_case;
2014                 case AST_DEVICE_RINGING:
2015                         if (conditions & QUEUE_EMPTY_RINGING) {
2016                                 ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
2017                                 break;
2018                         }
2019                         goto default_case;
2020                 case AST_DEVICE_UNKNOWN:
2021                         if (conditions & QUEUE_EMPTY_UNKNOWN) {
2022                                 ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
2023                                 break;
2024                         }
2025                         /* Fall-through */
2026                 default:
2027                 default_case:
2028                         if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
2029                                 ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
2030                                 break;
2031                         } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
2032                                 ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
2033                                 break;
2034                         } else {
2035                                 ao2_ref(member, -1);
2036                                 ao2_iterator_destroy(&mem_iter);
2037                                 ao2_unlock(q);
2038                                 ast_debug(4, "%s is available.\n", member->membername);
2039                                 return 0;
2040                         }
2041                         break;
2042                 }
2043         }
2044         ao2_iterator_destroy(&mem_iter);
2045
2046         ao2_unlock(q);
2047         return -1;
2048 }
2049
2050 /*! \brief set a member's status based on device state of that member's state_interface.
2051  *
2052  * Lock interface list find sc, iterate through each queues queue_member list for member to
2053  * update state inside queues
2054 */
2055 static void update_status(struct call_queue *q, struct member *m, const int status)
2056 {
2057         m->status = status;
2058
2059         queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
2060 }
2061
2062 /*!
2063  * \internal \brief Determine if a queue member is available
2064  * \retval 1 if the member is available
2065  * \retval 0 if the member is not available
2066  */
2067 static int is_member_available(struct member *mem)
2068 {
2069         int available = 0;
2070
2071         switch (mem->status) {
2072                 case AST_DEVICE_INVALID:
2073                 case AST_DEVICE_UNAVAILABLE:
2074                         break;
2075                 case AST_DEVICE_INUSE:
2076                 case AST_DEVICE_BUSY:
2077                 case AST_DEVICE_RINGING:
2078                 case AST_DEVICE_RINGINUSE:
2079                 case AST_DEVICE_ONHOLD:
2080                         if (!mem->ringinuse) {
2081                                 break;
2082                         }
2083                         /* else fall through */
2084                 case AST_DEVICE_NOT_INUSE:
2085                 case AST_DEVICE_UNKNOWN:
2086                         if (!mem->paused) {
2087                                 available = 1;
2088                         }
2089                         break;
2090         }
2091
2092         return available;
2093 }
2094
2095 /*! \brief set a member's status based on device state of that member's interface*/
2096 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *msg)
2097 {
2098         struct ao2_iterator miter, qiter;
2099         struct ast_device_state_message *dev_state;
2100         struct member *m;
2101         struct call_queue *q;
2102         char interface[80], *slash_pos;
2103         int found = 0;                  /* Found this member in any queue */
2104         int found_member;               /* Found this member in this queue */
2105         int avail = 0;                  /* Found an available member in this queue */
2106
2107         if (ast_device_state_message_type() != stasis_message_type(msg)) {
2108                 return;
2109         }
2110
2111         dev_state = stasis_message_data(msg);
2112         if (dev_state->eid) {
2113                 /* ignore non-aggregate states */
2114                 return;
2115         }
2116
2117         qiter = ao2_iterator_init(queues, 0);
2118         while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2119                 ao2_lock(q);
2120
2121                 avail = 0;
2122                 found_member = 0;
2123                 miter = ao2_iterator_init(q->members, 0);
2124                 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2125                         if (!found_member) {
2126                                 ast_copy_string(interface, m->state_interface, sizeof(interface));
2127
2128                                 if ((slash_pos = strchr(interface, '/'))) {
2129                                         if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2130                                                 *slash_pos = '\0';
2131                                         }
2132                                 }
2133
2134                                 if (!strcasecmp(interface, dev_state->device)) {
2135                                         found_member = 1;
2136                                         update_status(q, m, dev_state->state);
2137                                 }
2138                         }
2139
2140                         /* check every member until we find one NOT_INUSE */
2141                         if (!avail) {
2142                                 avail = is_member_available(m);
2143                         }
2144                         if (avail && found_member) {
2145                                 /* early exit as we've found an available member and the member of interest */
2146                                 ao2_ref(m, -1);
2147                                 break;
2148                         }
2149                 }
2150
2151                 if (found_member) {
2152                         found = 1;
2153                         if (avail) {
2154                                 ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
2155                         } else {
2156                                 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
2157                         }
2158                 }
2159
2160                 ao2_iterator_destroy(&miter);
2161
2162                 ao2_unlock(q);
2163                 queue_t_unref(q, "Done with iterator");
2164         }
2165         ao2_iterator_destroy(&qiter);
2166
2167         if (found) {
2168                 ast_debug(1, "Device '%s' changed to state '%d' (%s)\n",
2169                         dev_state->device,
2170                         dev_state->state,
2171                         ast_devstate2str(dev_state->state));
2172         } else {
2173                 ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
2174                         dev_state->device,
2175                         dev_state->state,
2176                         ast_devstate2str(dev_state->state));
2177         }
2178
2179         return;
2180 }
2181
2182 /*! \brief Helper function which converts from extension state to device state values */
2183 static int extensionstate2devicestate(int state)
2184 {
2185         switch (state) {
2186         case AST_EXTENSION_NOT_INUSE:
2187                 state = AST_DEVICE_NOT_INUSE;
2188                 break;
2189         case AST_EXTENSION_INUSE:
2190                 state = AST_DEVICE_INUSE;
2191                 break;
2192         case AST_EXTENSION_BUSY:
2193                 state = AST_DEVICE_BUSY;
2194                 break;
2195         case AST_EXTENSION_RINGING:
2196                 state = AST_DEVICE_RINGING;
2197                 break;
2198         case AST_EXTENSION_ONHOLD:
2199                 state = AST_DEVICE_ONHOLD;
2200                 break;
2201         case AST_EXTENSION_UNAVAILABLE:
2202                 state = AST_DEVICE_UNAVAILABLE;
2203                 break;
2204         case AST_EXTENSION_REMOVED:
2205         case AST_EXTENSION_DEACTIVATED:
2206         default:
2207                 state = AST_DEVICE_INVALID;
2208                 break;
2209         }
2210
2211         return state;
2212 }
2213
2214 static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
2215 {
2216         struct ao2_iterator miter, qiter;
2217         struct member *m;
2218         struct call_queue *q;
2219         int state = info->exten_state;
2220         int found = 0, device_state = extensionstate2devicestate(state);
2221
2222         /* only interested in extension state updates involving device states */
2223         if (info->reason != AST_HINT_UPDATE_DEVICE) {
2224                 return 0;
2225         }
2226
2227         qiter = ao2_iterator_init(queues, 0);
2228         while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2229                 ao2_lock(q);
2230
2231                 miter = ao2_iterator_init(q->members, 0);
2232                 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2233                         if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
2234                                 update_status(q, m, device_state);
2235                                 ao2_ref(m, -1);
2236                                 found = 1;
2237                                 break;
2238                         }
2239                 }
2240                 ao2_iterator_destroy(&miter);
2241
2242                 ao2_unlock(q);
2243                 queue_t_unref(q, "Done with iterator");
2244         }
2245         ao2_iterator_destroy(&qiter);
2246
2247         if (found) {
2248                 ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2249         } else {
2250                 ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
2251                           exten, context, device_state, ast_devstate2str(device_state));
2252         }
2253
2254         return 0;
2255 }
2256
2257 /*! \brief Return the current state of a member */
2258 static int get_queue_member_status(struct member *cur)
2259 {
2260         return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
2261 }
2262
2263 /*! \brief allocate space for new queue member and set fields based on parameters passed */
2264 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
2265 {
2266         struct member *cur;
2267
2268         if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
2269                 cur->ringinuse = ringinuse;
2270                 cur->penalty = penalty;
2271                 cur->paused = paused;
2272                 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2273                 if (!ast_strlen_zero(state_interface)) {
2274                         ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
2275                 } else {
2276                         ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
2277                 }
2278                 if (!ast_strlen_zero(membername)) {
2279                         ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2280                 } else {
2281                         ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2282                 }
2283                 if (!strchr(cur->interface, '/')) {
2284                         ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2285                 }
2286                 if (!strncmp(cur->state_interface, "hint:", 5)) {
2287                         char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2288                         char *exten = strsep(&context, "@") + 5;
2289
2290                         ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2291                         ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2292                 }
2293                 cur->status = get_queue_member_status(cur);
2294         }
2295
2296         return cur;
2297 }
2298
2299
2300 static int compress_char(const char c)
2301 {
2302         if (c < 32) {
2303                 return 0;
2304         } else if (c > 96) {
2305                 return c - 64;
2306         }
2307         return c - 32;
2308 }
2309
2310 static int member_hash_fn(const void *obj, const int flags)
2311 {
2312         const struct member *mem = obj;
2313         const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
2314         const char *chname = strchr(interface, '/');
2315         int ret = 0, i;
2316
2317         if (!chname) {
2318                 chname = interface;
2319         }
2320         for (i = 0; i < 5 && chname[i]; i++) {
2321                 ret += compress_char(chname[i]) << (i * 6);
2322         }
2323         return ret;
2324 }
2325
2326 static int member_cmp_fn(void *obj1, void *obj2, int flags)
2327 {
2328         struct member *mem1 = obj1;
2329         struct member *mem2 = obj2;
2330         const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
2331
2332         return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
2333 }
2334
2335 /*!
2336  * \brief Initialize Queue default values.
2337  * \note the queue's lock  must be held before executing this function
2338 */
2339 static void init_queue(struct call_queue *q)
2340 {
2341         int i;
2342         struct penalty_rule *pr_iter;
2343
2344         q->dead = 0;
2345         q->retry = DEFAULT_RETRY;
2346         q->timeout = DEFAULT_TIMEOUT;
2347         q->maxlen = 0;
2348         q->announcefrequency = 0;
2349         q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
2350         q->announceholdtime = 1;
2351         q->announcepositionlimit = 10; /* Default 10 positions */
2352         q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
2353         q->roundingseconds = 0; /* Default - don't announce seconds */
2354         q->servicelevel = 0;
2355         q->ringinuse = 1;
2356         q->announce_to_first_user = 0;
2357         q->setinterfacevar = 0;
2358         q->setqueuevar = 0;
2359         q->setqueueentryvar = 0;
2360         q->autofill = autofill_default;
2361         q->montype = montype_default;
2362         q->monfmt[0] = '\0';
2363         q->reportholdtime = 0;
2364         q->wrapuptime = 0;
2365         q->penaltymemberslimit = 0;
2366         q->joinempty = 0;
2367         q->leavewhenempty = 0;
2368         q->memberdelay = 0;
2369         q->weight = 0;
2370         q->timeoutrestart = 0;
2371         q->periodicannouncefrequency = 0;
2372         q->randomperiodicannounce = 0;
2373         q->numperiodicannounce = 0;
2374         q->autopause = QUEUE_AUTOPAUSE_OFF;
2375         q->timeoutpriority = TIMEOUT_PRIORITY_APP;
2376         q->autopausedelay = 0;
2377         if (!q->members) {
2378                 if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
2379                         /* linear strategy depends on order, so we have to place all members in a single bucket */
2380                         q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
2381                 } else {
2382                         q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
2383                 }
2384         }
2385         q->found = 1;
2386
2387         ast_string_field_set(q, sound_next, "queue-youarenext");
2388         ast_string_field_set(q, sound_thereare, "queue-thereare");
2389         ast_string_field_set(q, sound_calls, "queue-callswaiting");
2390         ast_string_field_set(q, queue_quantity1, "queue-quantity1");
2391         ast_string_field_set(q, queue_quantity2, "queue-quantity2");
2392         ast_string_field_set(q, sound_holdtime, "queue-holdtime");
2393         ast_string_field_set(q, sound_minutes, "queue-minutes");
2394         ast_string_field_set(q, sound_minute, "queue-minute");
2395         ast_string_field_set(q, sound_seconds, "queue-seconds");
2396         ast_string_field_set(q, sound_thanks, "queue-thankyou");
2397         ast_string_field_set(q, sound_reporthold, "queue-reporthold");
2398
2399         if (!q->sound_periodicannounce[0]) {
2400                 q->sound_periodicannounce[0] = ast_str_create(32);
2401         }
2402
2403         if (q->sound_periodicannounce[0]) {
2404                 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
2405         }
2406
2407         for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
2408                 if (q->sound_periodicannounce[i]) {
2409                         ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
2410                 }
2411         }
2412
2413         while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
2414                 ast_free(pr_iter);
2415         }
2416
2417         /* On restart assume no members are available.
2418          * The queue_avail hint is a boolean state to indicate whether a member is available or not.
2419          *
2420          * This seems counter intuitive, but is required to light a BLF
2421          * AST_DEVICE_INUSE indicates no members are available.
2422          * AST_DEVICE_NOT_INUSE indicates a member is available.
2423          */
2424         ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
2425 }
2426
2427 static void clear_queue(struct call_queue *q)
2428 {
2429         q->holdtime = 0;
2430         q->callscompleted = 0;
2431         q->callsabandoned = 0;
2432         q->callscompletedinsl = 0;
2433         q->talktime = 0;
2434
2435         if (q->members) {
2436                 struct member *mem;
2437                 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
2438                 while ((mem = ao2_iterator_next(&mem_iter))) {
2439                         mem->calls = 0;
2440                         mem->lastcall = 0;
2441                         ao2_ref(mem, -1);
2442                 }
2443                 ao2_iterator_destroy(&mem_iter);
2444         }
2445 }
2446
2447 /*!
2448  * \brief Change queue penalty by adding rule.
2449  *
2450  * Check rule for errors with time or fomatting, see if rule is relative to rest
2451  * of queue, iterate list of rules to find correct insertion point, insert and return.
2452  * \retval -1 on failure
2453  * \retval 0 on success
2454  * \note Call this with the rule_lists locked
2455 */
2456 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
2457 {
2458         char *timestr, *maxstr, *minstr, *contentdup;
2459         struct penalty_rule *rule = NULL, *rule_iter;
2460         struct rule_list *rl_iter;
2461         int penaltychangetime, inserted = 0;
2462
2463         if (!(rule = ast_calloc(1, sizeof(*rule)))) {
2464                 return -1;
2465         }
2466
2467         contentdup = ast_strdupa(content);
2468
2469         if (!(maxstr = strchr(contentdup, ','))) {
2470                 ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
2471                 ast_free(rule);
2472                 return -1;
2473         }
2474
2475         *maxstr++ = '\0';
2476         timestr = contentdup;
2477
2478         if ((penaltychangetime = atoi(timestr)) < 0) {
2479                 ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
2480                 ast_free(rule);
2481                 return -1;
2482         }
2483
2484         rule->time = penaltychangetime;
2485
2486         if ((minstr = strchr(maxstr,','))) {
2487                 *minstr++ = '\0';
2488         }
2489
2490         /* The last check will evaluate true if either no penalty change is indicated for a given rule
2491          * OR if a min penalty change is indicated but no max penalty change is */
2492         if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
2493                 rule->max_relative = 1;
2494         }
2495
2496         rule->max_value = atoi(maxstr);
2497
2498         if (!ast_strlen_zero(minstr)) {
2499                 if (*minstr == '+' || *minstr == '-') {
2500                         rule->min_relative = 1;
2501                 }
2502                 rule->min_value = atoi(minstr);
2503         } else { /*there was no minimum specified, so assume this means no change*/
2504                 rule->min_relative = 1;
2505         }
2506
2507         /*We have the rule made, now we need to insert it where it belongs*/
2508         AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
2509                 if (strcasecmp(rl_iter->name, list_name)) {
2510                         continue;
2511                 }
2512
2513                 AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
2514                         if (rule->time < rule_iter->time) {
2515                                 AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
2516                                 inserted = 1;
2517                                 break;
2518                         }
2519                 }
2520                 AST_LIST_TRAVERSE_SAFE_END;
2521
2522                 if (!inserted) {
2523                         AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
2524                         inserted = 1;
2525                 }
2526
2527                 break;
2528         }
2529
2530         if (!inserted) {
2531                 ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
2532                 ast_free(rule);
2533                 return -1;
2534         }
2535         return 0;
2536 }
2537
2538 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
2539 {
2540         char *value_copy = ast_strdupa(value);
2541         char *option = NULL;
2542         while ((option = strsep(&value_copy, ","))) {
2543                 if (!strcasecmp(option, "paused")) {
2544                         *empty |= QUEUE_EMPTY_PAUSED;
2545                 } else if (!strcasecmp(option, "penalty")) {
2546                         *empty |= QUEUE_EMPTY_PENALTY;
2547                 } else if (!strcasecmp(option, "inuse")) {
2548                         *empty |= QUEUE_EMPTY_INUSE;
2549                 } else if (!strcasecmp(option, "ringing")) {
2550                         *empty |= QUEUE_EMPTY_RINGING;
2551                 } else if (!strcasecmp(option, "invalid")) {
2552                         *empty |= QUEUE_EMPTY_INVALID;
2553                 } else if (!strcasecmp(option, "wrapup")) {
2554                         *empty |= QUEUE_EMPTY_WRAPUP;
2555                 } else if (!strcasecmp(option, "unavailable")) {
2556                         *empty |= QUEUE_EMPTY_UNAVAILABLE;
2557                 } else if (!strcasecmp(option, "unknown")) {
2558                         *empty |= QUEUE_EMPTY_UNKNOWN;
2559                 } else if (!strcasecmp(option, "loose")) {
2560                         *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
2561                 } else if (!strcasecmp(option, "strict")) {
2562                         *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
2563                 } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
2564                         *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
2565                 } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
2566                         *empty = 0;
2567                 } else {
2568                         ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
2569                 }
2570         }
2571 }
2572
2573 /*! \brief Configure a queue parameter.
2574  *
2575  * The failunknown flag is set for config files (and static realtime) to show
2576  * errors for unknown parameters. It is cleared for dynamic realtime to allow
2577  *  extra fields in the tables.
2578  * \note For error reporting, line number is passed for .conf static configuration,
2579  * for Realtime queues, linenum is -1.
2580 */
2581 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
2582 {
2583         if (!strcasecmp(param, "musicclass") ||
2584                 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
2585                 ast_string_field_set(q, moh, val);
2586         } else if (!strcasecmp(param, "announce")) {
2587                 ast_string_field_set(q, announce, val);
2588         } else if (!strcasecmp(param, "context")) {
2589                 ast_string_field_set(q, context, val);
2590         } else if (!strcasecmp(param, "timeout")) {
2591                 q->timeout = atoi(val);
2592                 if (q->timeout < 0) {
2593                         q->timeout = DEFAULT_TIMEOUT;
2594                 }
2595         } else if (!strcasecmp(param, "ringinuse")) {
2596                 q->ringinuse = ast_true(val);
2597         } else if (!strcasecmp(param, "setinterfacevar")) {
2598                 q->setinterfacevar = ast_true(val);
2599         } else if (!strcasecmp(param, "setqueuevar")) {
2600                 q->setqueuevar = ast_true(val);
2601         } else if (!strcasecmp(param, "setqueueentryvar")) {
2602                 q->setqueueentryvar = ast_true(val);
2603         } else if (!strcasecmp(param, "monitor-format")) {
2604                 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
2605         } else if (!strcasecmp(param, "membermacro")) {
2606                 ast_string_field_set(q, membermacro, val);
2607         } else if (!strcasecmp(param, "membergosub")) {
2608                 ast_string_field_set(q, membergosub, val);
2609         } else if (!strcasecmp(param, "queue-youarenext")) {
2610                 ast_string_field_set(q, sound_next, val);
2611         } else if (!strcasecmp(param, "queue-thereare")) {
2612                 ast_string_field_set(q, sound_thereare, val);
2613         } else if (!strcasecmp(param, "queue-callswaiting")) {
2614                 ast_string_field_set(q, sound_calls, val);
2615         } else if (!strcasecmp(param, "queue-quantity1")) {
2616                 ast_string_field_set(q, queue_quantity1, val);
2617         } else if (!strcasecmp(param, "queue-quantity2")) {
2618                 ast_string_field_set(q, queue_quantity2, val);
2619         } else if (!strcasecmp(param, "queue-holdtime")) {
2620                 ast_string_field_set(q, sound_holdtime, val);
2621         } else if (!strcasecmp(param, "queue-minutes")) {
2622                 ast_string_field_set(q, sound_minutes, val);
2623         } else if (!strcasecmp(param, "queue-minute")) {
2624                 ast_string_field_set(q, sound_minute, val);
2625         } else if (!strcasecmp(param, "queue-seconds")) {
2626                 ast_string_field_set(q, sound_seconds, val);
2627         } else if (!strcasecmp(param, "queue-thankyou")) {
2628                 ast_string_field_set(q, sound_thanks, val);
2629         } else if (!strcasecmp(param, "queue-callerannounce")) {
2630                 ast_string_field_set(q, sound_callerannounce, val);
2631         } else if (!strcasecmp(param, "queue-reporthold")) {
2632                 ast_string_field_set(q, sound_reporthold, val);
2633         } else if (!strcasecmp(param, "announce-frequency")) {
2634                 q->announcefrequency = atoi(val);
2635         } else if (!strcasecmp(param, "announce-to-first-user")) {
2636                 q->announce_to_first_user = ast_true(val);
2637         } else if (!strcasecmp(param, "min-announce-frequency")) {
2638                 q->minannouncefrequency = atoi(val);
2639                 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
2640         } else if (!strcasecmp(param, "announce-round-seconds")) {
2641                 q->roundingseconds = atoi(val);
2642                 /* Rounding to any other values just doesn't make sense... */
2643                 if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
2644                         || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
2645                         if (linenum >= 0) {
2646                                 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
2647                                         "using 0 instead for queue '%s' at line %d of queues.conf\n",
2648                                         val, param, q->name, linenum);
2649                         } else {
2650                                 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
2651                                         "using 0 instead for queue '%s'\n", val, param, q->name);
2652                         }
2653                         q->roundingseconds=0;
2654                 }
2655         } else if (!strcasecmp(param, "announce-holdtime")) {
2656                 if (!strcasecmp(val, "once")) {
2657                         q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
2658                 } else if (ast_true(val)) {
2659                         q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
2660                 } else {
2661                         q->announceholdtime = 0;
2662                 }
2663         } else if (!strcasecmp(param, "announce-position")) {
2664                 if (!strcasecmp(val, "limit")) {
2665                         q->announceposition = ANNOUNCEPOSITION_LIMIT;
2666                 } else if (!strcasecmp(val, "more")) {
2667                         q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
2668                 } else if (ast_true(val)) {
2669                         q->announceposition = ANNOUNCEPOSITION_YES;
2670                 } else {
2671                         q->announceposition = ANNOUNCEPOSITION_NO;
2672                 }
2673         } else if (!strcasecmp(param, "announce-position-limit")) {
2674                 q->announcepositionlimit = atoi(val);
2675         } else if (!strcasecmp(param, "periodic-announce")) {
2676                 if (strchr(val, ',')) {
2677                         char *s, *buf = ast_strdupa(val);
2678                         unsigned int i = 0;
2679
2680                         while ((s = strsep(&buf, ",|"))) {
2681                                 if (!q->sound_periodicannounce[i]) {
2682                                         q->sound_periodicannounce[i] = ast_str_create(16);
2683                                 }
2684                                 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
2685                                 i++;
2686                                 if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
2687                                         break;
2688                                 }
2689                         }
2690                         q->numperiodicannounce = i;
2691                 } else {
2692                         ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
2693                         q->numperiodicannounce = 1;
2694                 }
2695         } else if (!strcasecmp(param, "periodic-announce-frequency")) {
2696                 q->periodicannouncefrequency = atoi(val);
2697         } else if (!strcasecmp(param, "relative-periodic-announce")) {
2698                 q->relativeperiodicannounce = ast_true(val);
2699         } else if (!strcasecmp(param, "random-periodic-announce")) {
2700                 q->randomperiodicannounce = ast_true(val);
2701         } else if (!strcasecmp(param, "retry")) {
2702                 q->retry = atoi(val);
2703                 if (q->retry <= 0) {
2704                         q->retry = DEFAULT_RETRY;
2705                 }
2706         } else if (!strcasecmp(param, "wrapuptime")) {
2707                 q->wrapuptime = atoi(val);
2708         } else if (!strcasecmp(param, "penaltymemberslimit")) {
2709                 if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
2710                         q->penaltymemberslimit = 0;
2711                 }
2712         } else if (!strcasecmp(param, "autofill")) {
2713                 q->autofill = ast_true(val);
2714         } else if (!strcasecmp(param, "monitor-type")) {
2715                 if (!strcasecmp(val, "mixmonitor")) {
2716                         q->montype = 1;
2717                 }
2718         } else if (!strcasecmp(param, "autopause")) {
2719                 q->autopause = autopause2int(val);
2720         } else if (!strcasecmp(param, "autopausedelay")) {
2721                 q->autopausedelay = atoi(val);
2722         } else if (!strcasecmp(param, "autopausebusy")) {
2723                 q->autopausebusy = ast_true(val);
2724         } else if (!strcasecmp(param, "autopauseunavail")) {
2725                 q->autopauseunavail = ast_true(val);
2726         } else if (!strcasecmp(param, "maxlen")) {
2727                 q->maxlen = atoi(val);
2728                 if (q->maxlen < 0) {
2729                         q->maxlen = 0;
2730                 }
2731         } else if (!strcasecmp(param, "servicelevel")) {
2732                 q->servicelevel= atoi(val);
2733         } else if (!strcasecmp(param, "strategy")) {
2734                 int strategy;
2735
2736                 /* We are a static queue and already have set this, no need to do it again */
2737                 if (failunknown) {
2738                         return;
2739                 }
2740                 strategy = strat2int(val);
2741                 if (strategy < 0) {
2742                         ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
2743                                 val, q->name);
2744                         q->strategy = QUEUE_STRATEGY_RINGALL;
2745                 }
2746                 if (strategy == q->strategy) {
2747                         return;
2748                 }
2749                 if (strategy == QUEUE_STRATEGY_LINEAR) {
2750                         ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
2751                         return;
2752                 }
2753                 q->strategy = strategy;
2754         } else if (!strcasecmp(param, "joinempty")) {
2755                 parse_empty_options(val, &q->joinempty, 1);
2756         } else if (!strcasecmp(param, "leavewhenempty")) {
2757                 parse_empty_options(val, &q->leavewhenempty, 0);
2758         } else if (!strcasecmp(param, "reportholdtime")) {
2759                 q->reportholdtime = ast_true(val);
2760         } else if (!strcasecmp(param, "memberdelay")) {
2761                 q->memberdelay = atoi(val);
2762         } else if (!strcasecmp(param, "weight")) {
2763                 q->weight = atoi(val);
2764         } else if (!strcasecmp(param, "timeoutrestart")) {
2765                 q->timeoutrestart = ast_true(val);
2766         } else if (!strcasecmp(param, "defaultrule")) {
2767                 ast_string_field_set(q, defaultrule, val);
2768         } else if (!strcasecmp(param, "timeoutpriority")) {
2769                 if (!strcasecmp(val, "conf")) {
2770                         q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
2771                 } else {
2772                         q->timeoutpriority = TIMEOUT_PRIORITY_APP;
2773                 }
2774         } else if (failunknown) {
2775                 if (linenum >= 0) {
2776                         ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
2777                                 q->name, param, linenum);
2778                 } else {
2779                         ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
2780                 }
2781         }
2782 }
2783
2784 /*! \internal
2785  * \brief If adding a single new member to a queue, use this function instead of ao2_linking.
2786  *        This adds round robin queue position data for a fresh member as well as links it.
2787  * \param queue Which queue the member is being added to
2788  * \param mem Which member is being added to the queue
2789  */
2790 static void member_add_to_queue(struct call_queue *queue, struct member *mem)
2791 {
2792         ao2_lock(queue->members);
2793         mem->queuepos = ao2_container_count(queue->members);
2794         ao2_link(queue->members, mem);
2795         ao2_unlock(queue->members);
2796 }
2797
2798 /*! \internal
2799  * \brief If removing a single member from a queue, use this function instead of ao2_unlinking.
2800  *        This will perform round robin queue position reordering for the remaining members.
2801  * \param queue Which queue the member is being removed from
2802  * \param member Which member is being removed from the queue
2803  */
2804 static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
2805 {
2806         ao2_lock(queue->members);
2807         queue_member_follower_removal(queue, mem);
2808         ao2_unlink(queue->members, mem);
2809         ao2_unlock(queue->members);
2810 }
2811
2812 /*!
2813  * \brief Find rt member record to update otherwise create one.
2814  *
2815  * Search for member in queue, if found update penalty/paused state,
2816  * if no member exists create one flag it as a RT member and add to queue member list.
2817 */
2818 static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
2819 {
2820         struct member *m;
2821         struct ao2_iterator mem_iter;
2822         int penalty = 0;
2823         int paused  = 0;
2824         int found = 0;
2825         int ringinuse = q->ringinuse;
2826
2827         const char *config_val;
2828         const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
2829         const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
2830         const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
2831         const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty");
2832         const char *paused_str = ast_variable_retrieve(member_config, interface, "paused");
2833
2834         if (ast_strlen_zero(rt_uniqueid)) {
2835                 ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
2836                 return;
2837         }
2838
2839         if (penalty_str) {
2840                 penalty = atoi(penalty_str);
2841                 if ((penalty < 0) && negative_penalty_invalid) {