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