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