Asterisk - The Open Source Telephony Project  GIT-master-a24979a
app_queue.c
Go to the documentation of this file.
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"
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="i">
189  <para>Ignore call forward requests from queue members and do nothing
190  when they are requested.</para>
191  </option>
192  <option name="I">
193  <para>Asterisk will ignore any connected line update requests or any redirecting party
194  update requests it may receive on this dial attempt.</para>
195  </option>
196  <option name="k">
197  <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
198  the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
199  </option>
200  <option name="K">
201  <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
202  the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
203  </option>
204  <option name="m">
205  <para>Custom music on hold class to use, which will override the music on hold class configured
206  in <filename>queues.conf</filename>, if specified.</para>
207  <para>Note that CHANNEL(musicclass), if set, will still override this option.</para>
208  </option>
209  <option name="n">
210  <para>No retries on the timeout; will exit this application and
211  go to the next step.</para>
212  </option>
213  <option name="r">
214  <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
215  </option>
216  <option name="R">
217  <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
218  </option>
219  <option name="t">
220  <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
221  </option>
222  <option name="T">
223  <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
224  </option>
225  <option name="w">
226  <para>Allow the <emphasis>called</emphasis> user to write the conversation to
227  disk via Monitor.</para>
228  </option>
229  <option name="W">
230  <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
231  disk via Monitor.</para>
232  </option>
233  <option name="x">
234  <para>Allow the <emphasis>called</emphasis> user to write the conversation
235  to disk via MixMonitor.</para>
236  </option>
237  <option name="X">
238  <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
239  disk via MixMonitor.</para>
240  </option>
241  </optionlist>
242  </parameter>
243  <parameter name="URL">
244  <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
245  </parameter>
246  <parameter name="announceoverride" argsep="&amp;">
247  <argument name="filename" required="true">
248  <para>Announcement file(s) to play to agent before bridging call, overriding the announcement(s)
249  configured in <filename>queues.conf</filename>, if any.</para>
250  </argument>
251  <argument name="filename2" multiple="true" />
252  </parameter>
253  <parameter name="timeout">
254  <para>Will cause the queue to fail out after a specified number of
255  seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
256  <replaceable>retry</replaceable> cycle.</para>
257  </parameter>
258  <parameter name="AGI">
259  <para>Will setup an AGI script to be executed on the calling party's channel once they are
260  connected to a queue member.</para>
261  </parameter>
262  <parameter name="macro">
263  <para>Will run a macro on the called party's channel (the queue member) once the parties are connected.</para>
264  <para>NOTE: Macros are deprecated, GoSub should be used instead.</para>
265  </parameter>
266  <parameter name="gosub">
267  <para>Will run a gosub on the called party's channel (the queue member)
268  once the parties are connected. The subroutine execution starts in the
269  named context at the s exten and priority 1.</para>
270  </parameter>
271  <parameter name="rule">
272  <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
273  </parameter>
274  <parameter name="position">
275  <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
276  would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
277  the caller third in the queue.</para>
278  </parameter>
279  </syntax>
280  <description>
281  <para>In addition to transferring the call, a call may be parked and then picked
282  up by another user.</para>
283  <para>This application will return to the dialplan if the queue does not exist, or
284  any of the join options cause the caller to not enter the queue.</para>
285  <para>This application does not automatically answer and should be preceeded
286  by an application such as Answer(), Progress(), or Ringing().</para>
287  <para>This application sets the following channel variables upon completion:</para>
288  <variablelist>
289  <variable name="QUEUESTATUS">
290  <para>The status of the call as a text string.</para>
291  <value name="TIMEOUT" />
292  <value name="FULL" />
293  <value name="JOINEMPTY" />
294  <value name="LEAVEEMPTY" />
295  <value name="JOINUNAVAIL" />
296  <value name="LEAVEUNAVAIL" />
297  <value name="CONTINUE" />
298  <value name="WITHDRAW" />
299  </variable>
300  <variable name="ABANDONED">
301  <para>If the call was not answered by an agent this variable will be TRUE.</para>
302  <value name="TRUE" />
303  </variable>
304  <variable name="DIALEDPEERNUMBER">
305  <para>Resource of the agent that was dialed set on the outbound channel.</para>
306  </variable>
307  <variable name="QUEUE_WITHDRAW_INFO">
308  <para>If the call was successfully withdrawn from the queue, and the withdraw request was provided with optional withdraw info, the withdraw info will be stored in this variable.</para>
309  </variable>
310  </variablelist>
311  </description>
312  <see-also>
313  <ref type="application">Queue</ref>
314  <ref type="application">QueueLog</ref>
315  <ref type="application">AddQueueMember</ref>
316  <ref type="application">RemoveQueueMember</ref>
317  <ref type="application">PauseQueueMember</ref>
318  <ref type="application">UnpauseQueueMember</ref>
319  <ref type="function">QUEUE_VARIABLES</ref>
320  <ref type="function">QUEUE_MEMBER</ref>
321  <ref type="function">QUEUE_MEMBER_COUNT</ref>
322  <ref type="function">QUEUE_EXISTS</ref>
323  <ref type="function">QUEUE_GET_CHANNEL</ref>
324  <ref type="function">QUEUE_WAITING_COUNT</ref>
325  <ref type="function">QUEUE_MEMBER_LIST</ref>
326  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
327  </see-also>
328  </application>
329  <application name="AddQueueMember" language="en_US">
330  <synopsis>
331  Dynamically adds queue members.
332  </synopsis>
333  <syntax>
334  <parameter name="queuename" required="true" />
335  <parameter name="interface" />
336  <parameter name="penalty" />
337  <parameter name="options" />
338  <parameter name="membername" />
339  <parameter name="stateinterface" />
340  <parameter name="wrapuptime" />
341  </syntax>
342  <description>
343  <para>Dynamically adds interface to an existing queue. If the interface is
344  already in the queue it will return an error.</para>
345  <para>This application sets the following channel variable upon completion:</para>
346  <variablelist>
347  <variable name="AQMSTATUS">
348  <para>The status of the attempt to add a queue member as a text string.</para>
349  <value name="ADDED" />
350  <value name="MEMBERALREADY" />
351  <value name="NOSUCHQUEUE" />
352  </variable>
353  </variablelist>
354  </description>
355  <see-also>
356  <ref type="application">Queue</ref>
357  <ref type="application">QueueLog</ref>
358  <ref type="application">AddQueueMember</ref>
359  <ref type="application">RemoveQueueMember</ref>
360  <ref type="application">PauseQueueMember</ref>
361  <ref type="application">UnpauseQueueMember</ref>
362  <ref type="function">QUEUE_VARIABLES</ref>
363  <ref type="function">QUEUE_MEMBER</ref>
364  <ref type="function">QUEUE_MEMBER_COUNT</ref>
365  <ref type="function">QUEUE_EXISTS</ref>
366  <ref type="function">QUEUE_GET_CHANNEL</ref>
367  <ref type="function">QUEUE_WAITING_COUNT</ref>
368  <ref type="function">QUEUE_MEMBER_LIST</ref>
369  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
370  </see-also>
371  </application>
372  <application name="RemoveQueueMember" language="en_US">
373  <synopsis>
374  Dynamically removes queue members.
375  </synopsis>
376  <syntax>
377  <parameter name="queuename" required="true" />
378  <parameter name="interface" />
379  </syntax>
380  <description>
381  <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
382  <para>This application sets the following channel variable upon completion:</para>
383  <variablelist>
384  <variable name="RQMSTATUS">
385  <value name="REMOVED" />
386  <value name="NOTINQUEUE" />
387  <value name="NOSUCHQUEUE" />
388  <value name="NOTDYNAMIC" />
389  </variable>
390  </variablelist>
391  <example title="Remove queue member">
392  same => n,RemoveQueueMember(techsupport,SIP/3000)
393  </example>
394  </description>
395  <see-also>
396  <ref type="application">Queue</ref>
397  <ref type="application">QueueLog</ref>
398  <ref type="application">AddQueueMember</ref>
399  <ref type="application">RemoveQueueMember</ref>
400  <ref type="application">PauseQueueMember</ref>
401  <ref type="application">UnpauseQueueMember</ref>
402  <ref type="function">QUEUE_VARIABLES</ref>
403  <ref type="function">QUEUE_MEMBER</ref>
404  <ref type="function">QUEUE_MEMBER_COUNT</ref>
405  <ref type="function">QUEUE_EXISTS</ref>
406  <ref type="function">QUEUE_GET_CHANNEL</ref>
407  <ref type="function">QUEUE_WAITING_COUNT</ref>
408  <ref type="function">QUEUE_MEMBER_LIST</ref>
409  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
410  </see-also>
411  </application>
412  <application name="PauseQueueMember" language="en_US">
413  <synopsis>
414  Pauses a queue member.
415  </synopsis>
416  <syntax>
417  <parameter name="queuename" />
418  <parameter name="interface" required="true" />
419  <parameter name="options" />
420  <parameter name="reason">
421  <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
422  </parameter>
423  </syntax>
424  <description>
425  <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
426  This prevents any calls from being sent from the queue to the interface until it is
427  unpaused with UnpauseQueueMember or the manager interface. If no queuename is given,
428  the interface is paused in every queue it is a member of. The application will fail if the
429  interface is not found.</para>
430  <para>This application sets the following channel variable upon completion:</para>
431  <variablelist>
432  <variable name="PQMSTATUS">
433  <para>The status of the attempt to pause a queue member as a text string.</para>
434  <value name="PAUSED" />
435  <value name="NOTFOUND" />
436  </variable>
437  </variablelist>
438  <example title="Pause queue member">
439  same => n,PauseQueueMember(,SIP/3000)
440  </example>
441  </description>
442  <see-also>
443  <ref type="application">Queue</ref>
444  <ref type="application">QueueLog</ref>
445  <ref type="application">AddQueueMember</ref>
446  <ref type="application">RemoveQueueMember</ref>
447  <ref type="application">PauseQueueMember</ref>
448  <ref type="application">UnpauseQueueMember</ref>
449  <ref type="function">QUEUE_VARIABLES</ref>
450  <ref type="function">QUEUE_MEMBER</ref>
451  <ref type="function">QUEUE_MEMBER_COUNT</ref>
452  <ref type="function">QUEUE_EXISTS</ref>
453  <ref type="function">QUEUE_GET_CHANNEL</ref>
454  <ref type="function">QUEUE_WAITING_COUNT</ref>
455  <ref type="function">QUEUE_MEMBER_LIST</ref>
456  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
457  </see-also>
458  </application>
459  <application name="UnpauseQueueMember" language="en_US">
460  <synopsis>
461  Unpauses a queue member.
462  </synopsis>
463  <syntax>
464  <parameter name="queuename" />
465  <parameter name="interface" required="true" />
466  <parameter name="options" />
467  <parameter name="reason">
468  <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
469  </parameter>
470  </syntax>
471  <description>
472  <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
473  and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
474  <para>This application sets the following channel variable upon completion:</para>
475  <variablelist>
476  <variable name="UPQMSTATUS">
477  <para>The status of the attempt to unpause a queue member as a text string.</para>
478  <value name="UNPAUSED" />
479  <value name="NOTFOUND" />
480  </variable>
481  </variablelist>
482  <example title="Unpause queue member">
483  same => n,UnpauseQueueMember(,SIP/3000)
484  </example>
485  </description>
486  <see-also>
487  <ref type="application">Queue</ref>
488  <ref type="application">QueueLog</ref>
489  <ref type="application">AddQueueMember</ref>
490  <ref type="application">RemoveQueueMember</ref>
491  <ref type="application">PauseQueueMember</ref>
492  <ref type="application">UnpauseQueueMember</ref>
493  <ref type="function">QUEUE_VARIABLES</ref>
494  <ref type="function">QUEUE_MEMBER</ref>
495  <ref type="function">QUEUE_MEMBER_COUNT</ref>
496  <ref type="function">QUEUE_EXISTS</ref>
497  <ref type="function">QUEUE_GET_CHANNEL</ref>
498  <ref type="function">QUEUE_WAITING_COUNT</ref>
499  <ref type="function">QUEUE_MEMBER_LIST</ref>
500  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
501  </see-also>
502  </application>
503  <application name="QueueLog" language="en_US">
504  <synopsis>
505  Writes to the queue_log file.
506  </synopsis>
507  <syntax>
508  <parameter name="queuename" required="true" />
509  <parameter name="uniqueid" required="true" />
510  <parameter name="agent" required="true" />
511  <parameter name="event" required="true" />
512  <parameter name="additionalinfo" />
513  </syntax>
514  <description>
515  <para>Allows you to write your own events into the queue log.</para>
516  <example title="Log custom queue event">
517  same => n,QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)
518  </example>
519  </description>
520  <see-also>
521  <ref type="application">Queue</ref>
522  <ref type="application">QueueLog</ref>
523  <ref type="application">AddQueueMember</ref>
524  <ref type="application">RemoveQueueMember</ref>
525  <ref type="application">PauseQueueMember</ref>
526  <ref type="application">UnpauseQueueMember</ref>
527  <ref type="function">QUEUE_VARIABLES</ref>
528  <ref type="function">QUEUE_MEMBER</ref>
529  <ref type="function">QUEUE_MEMBER_COUNT</ref>
530  <ref type="function">QUEUE_EXISTS</ref>
531  <ref type="function">QUEUE_GET_CHANNEL</ref>
532  <ref type="function">QUEUE_WAITING_COUNT</ref>
533  <ref type="function">QUEUE_MEMBER_LIST</ref>
534  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
535  </see-also>
536  </application>
537  <application name="QueueUpdate" language="en_US">
538  <synopsis>
539  Writes to the queue_log file for outbound calls and updates Realtime Data.
540  Is used at h extension to be able to have all the parameters.
541  </synopsis>
542  <syntax>
543  <parameter name="queuename" required="true" />
544  <parameter name="uniqueid" required="true" />
545  <parameter name="agent" required="true" />
546  <parameter name="status" required="true" />
547  <parameter name="talktime" required="true" />
548  <parameter name="params" required="false" />
549  </syntax>
550  <description>
551  <para>Allows you to write Outbound events into the queue log.</para>
552  <example title="Write outbound event into queue log">
553  exten => h,1,QueueUpdate(${QUEUE}, ${UNIQUEID}, ${AGENT}, ${DIALSTATUS}, ${ANSWEREDTIME}, ${DIALEDTIME} | ${DIALEDNUMBER})
554  </example>
555  </description>
556  </application>
557  <function name="QUEUE_VARIABLES" language="en_US">
558  <synopsis>
559  Return Queue information in variables.
560  </synopsis>
561  <syntax>
562  <parameter name="queuename" required="true">
563  <enumlist>
564  <enum name="QUEUEMAX">
565  <para>Maxmimum number of calls allowed.</para>
566  </enum>
567  <enum name="QUEUESTRATEGY">
568  <para>The strategy of the queue.</para>
569  </enum>
570  <enum name="QUEUECALLS">
571  <para>Number of calls currently in the queue.</para>
572  </enum>
573  <enum name="QUEUEHOLDTIME">
574  <para>Current average hold time.</para>
575  </enum>
576  <enum name="QUEUECOMPLETED">
577  <para>Number of completed calls for the queue.</para>
578  </enum>
579  <enum name="QUEUEABANDONED">
580  <para>Number of abandoned calls.</para>
581  </enum>
582  <enum name="QUEUESRVLEVEL">
583  <para>Queue service level.</para>
584  </enum>
585  <enum name="QUEUESRVLEVELPERF">
586  <para>Current service level performance.</para>
587  </enum>
588  </enumlist>
589  </parameter>
590  </syntax>
591  <description>
592  <para>Makes the following queue variables available.</para>
593  <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
594  </description>
595  <see-also>
596  <ref type="application">Queue</ref>
597  <ref type="application">QueueLog</ref>
598  <ref type="application">AddQueueMember</ref>
599  <ref type="application">RemoveQueueMember</ref>
600  <ref type="application">PauseQueueMember</ref>
601  <ref type="application">UnpauseQueueMember</ref>
602  <ref type="function">QUEUE_VARIABLES</ref>
603  <ref type="function">QUEUE_MEMBER</ref>
604  <ref type="function">QUEUE_MEMBER_COUNT</ref>
605  <ref type="function">QUEUE_EXISTS</ref>
606  <ref type="function">QUEUE_GET_CHANNEL</ref>
607  <ref type="function">QUEUE_WAITING_COUNT</ref>
608  <ref type="function">QUEUE_MEMBER_LIST</ref>
609  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
610  </see-also>
611  </function>
612  <function name="QUEUE_MEMBER" language="en_US">
613  <synopsis>
614  Provides a count of queue members based on the provided criteria, or updates a
615  queue member's settings.
616  </synopsis>
617  <syntax>
618  <parameter name="queuename" required="false" />
619  <parameter name="option" required="true">
620  <enumlist>
621  <enum name="logged">
622  <para>Returns the number of logged-in members for the specified queue.</para>
623  </enum>
624  <enum name="free">
625  <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>
626  </enum>
627  <enum name="ready">
628  <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
629  </enum>
630  <enum name="count">
631  <para>Returns the total number of members for the specified queue.</para>
632  </enum>
633  <enum name="penalty">
634  <para>Gets or sets queue member penalty. If
635  <replaceable>queuename</replaceable> is not specified
636  when setting the penalty then the penalty is set in all queues
637  the interface is a member.</para>
638  </enum>
639  <enum name="paused">
640  <para>Gets or sets queue member paused status. If
641  <replaceable>queuename</replaceable> is not specified
642  when setting the paused status then the paused status is set
643  in all queues the interface is a member.</para>
644  </enum>
645  <enum name="ringinuse">
646  <para>Gets or sets queue member ringinuse. If
647  <replaceable>queuename</replaceable> is not specified
648  when setting ringinuse then ringinuse is set
649  in all queues the interface is a member.</para>
650  </enum>
651  </enumlist>
652  </parameter>
653  <parameter name="interface" required="false" />
654  </syntax>
655  <description>
656  <para>Allows access to queue counts [R] and member information [R/W].</para>
657  <para><replaceable>queuename</replaceable> is required for all read operations.</para>
658  <para><replaceable>interface</replaceable> is required for all member operations.</para>
659  </description>
660  <see-also>
661  <ref type="application">Queue</ref>
662  <ref type="application">QueueLog</ref>
663  <ref type="application">AddQueueMember</ref>
664  <ref type="application">RemoveQueueMember</ref>
665  <ref type="application">PauseQueueMember</ref>
666  <ref type="application">UnpauseQueueMember</ref>
667  <ref type="function">QUEUE_VARIABLES</ref>
668  <ref type="function">QUEUE_MEMBER</ref>
669  <ref type="function">QUEUE_MEMBER_COUNT</ref>
670  <ref type="function">QUEUE_EXISTS</ref>
671  <ref type="function">QUEUE_GET_CHANNEL</ref>
672  <ref type="function">QUEUE_WAITING_COUNT</ref>
673  <ref type="function">QUEUE_MEMBER_LIST</ref>
674  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
675  </see-also>
676  </function>
677  <function name="QUEUE_MEMBER_COUNT" language="en_US">
678  <synopsis>
679  Count number of members answering a queue.
680  </synopsis>
681  <syntax>
682  <parameter name="queuename" required="true" />
683  </syntax>
684  <description>
685  <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
686  <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
687  </description>
688  <see-also>
689  <ref type="application">Queue</ref>
690  <ref type="application">QueueLog</ref>
691  <ref type="application">AddQueueMember</ref>
692  <ref type="application">RemoveQueueMember</ref>
693  <ref type="application">PauseQueueMember</ref>
694  <ref type="application">UnpauseQueueMember</ref>
695  <ref type="function">QUEUE_VARIABLES</ref>
696  <ref type="function">QUEUE_MEMBER</ref>
697  <ref type="function">QUEUE_MEMBER_COUNT</ref>
698  <ref type="function">QUEUE_EXISTS</ref>
699  <ref type="function">QUEUE_GET_CHANNEL</ref>
700  <ref type="function">QUEUE_WAITING_COUNT</ref>
701  <ref type="function">QUEUE_MEMBER_LIST</ref>
702  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
703  </see-also>
704  </function>
705  <function name="QUEUE_EXISTS" language="en_US">
706  <synopsis>
707  Check if a named queue exists on this server
708  </synopsis>
709  <syntax>
710  <parameter name="queuename" />
711  </syntax>
712  <description>
713  <para>Returns 1 if the specified queue exists, 0 if it does not</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_GET_CHANNEL</ref>
727  <ref type="function">QUEUE_WAITING_COUNT</ref>
728  <ref type="function">QUEUE_MEMBER_LIST</ref>
729  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
730  </see-also>
731  </function>
732  <function name="QUEUE_GET_CHANNEL" language="en_US">
733  <synopsis>
734  Return caller at the specified position in a queue.
735  </synopsis>
736  <syntax>
737  <parameter name="queuename" required="true" />
738  <parameter name="position" />
739  </syntax>
740  <description>
741  <para>Returns the caller channel at <replaceable>position</replaceable> in the specified <replaceable>queuename</replaceable>.</para>
742  <para>If <replaceable>position</replaceable> is unspecified the first channel is returned.</para>
743  </description>
744  <see-also>
745  <ref type="application">Queue</ref>
746  <ref type="application">QueueLog</ref>
747  <ref type="application">AddQueueMember</ref>
748  <ref type="application">RemoveQueueMember</ref>
749  <ref type="application">PauseQueueMember</ref>
750  <ref type="application">UnpauseQueueMember</ref>
751  <ref type="function">QUEUE_VARIABLES</ref>
752  <ref type="function">QUEUE_MEMBER</ref>
753  <ref type="function">QUEUE_MEMBER_COUNT</ref>
754  <ref type="function">QUEUE_EXISTS</ref>
755  <ref type="function">QUEUE_WAITING_COUNT</ref>
756  <ref type="function">QUEUE_MEMBER_LIST</ref>
757  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
758  </see-also>
759  </function>
760  <function name="QUEUE_WAITING_COUNT" language="en_US">
761  <synopsis>
762  Count number of calls currently waiting in a queue.
763  </synopsis>
764  <syntax>
765  <parameter name="queuename" />
766  </syntax>
767  <description>
768  <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
769  </description>
770  <see-also>
771  <ref type="application">Queue</ref>
772  <ref type="application">QueueLog</ref>
773  <ref type="application">AddQueueMember</ref>
774  <ref type="application">RemoveQueueMember</ref>
775  <ref type="application">PauseQueueMember</ref>
776  <ref type="application">UnpauseQueueMember</ref>
777  <ref type="function">QUEUE_VARIABLES</ref>
778  <ref type="function">QUEUE_MEMBER</ref>
779  <ref type="function">QUEUE_MEMBER_COUNT</ref>
780  <ref type="function">QUEUE_EXISTS</ref>
781  <ref type="function">QUEUE_GET_CHANNEL</ref>
782  <ref type="function">QUEUE_WAITING_COUNT</ref>
783  <ref type="function">QUEUE_MEMBER_LIST</ref>
784  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
785  </see-also>
786  </function>
787  <function name="QUEUE_MEMBER_LIST" language="en_US">
788  <synopsis>
789  Returns a list of interfaces on a queue.
790  </synopsis>
791  <syntax>
792  <parameter name="queuename" required="true" />
793  </syntax>
794  <description>
795  <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
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  <function name="QUEUE_MEMBER_PENALTY" language="en_US">
815  <synopsis>
816  Gets or sets queue members penalty.
817  </synopsis>
818  <syntax>
819  <parameter name="queuename" required="true" />
820  <parameter name="interface" required="true" />
821  </syntax>
822  <description>
823  <para>Gets or sets queue members penalty.</para>
824  <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
825  </description>
826  <see-also>
827  <ref type="application">Queue</ref>
828  <ref type="application">QueueLog</ref>
829  <ref type="application">AddQueueMember</ref>
830  <ref type="application">RemoveQueueMember</ref>
831  <ref type="application">PauseQueueMember</ref>
832  <ref type="application">UnpauseQueueMember</ref>
833  <ref type="function">QUEUE_VARIABLES</ref>
834  <ref type="function">QUEUE_MEMBER</ref>
835  <ref type="function">QUEUE_MEMBER_COUNT</ref>
836  <ref type="function">QUEUE_EXISTS</ref>
837  <ref type="function">QUEUE_GET_CHANNEL</ref>
838  <ref type="function">QUEUE_WAITING_COUNT</ref>
839  <ref type="function">QUEUE_MEMBER_LIST</ref>
840  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
841  </see-also>
842  </function>
843  <manager name="QueueStatus" language="en_US">
844  <synopsis>
845  Show queue status.
846  </synopsis>
847  <syntax>
848  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
849  <parameter name="Queue">
850  <para>Limit the response to the status of the specified queue.</para>
851  </parameter>
852  <parameter name="Member">
853  <para>Limit the response to the status of the specified member.</para>
854  </parameter>
855  </syntax>
856  <description>
857  <para>Check the status of one or more queues.</para>
858  </description>
859  </manager>
860  <manager name="QueueSummary" language="en_US">
861  <synopsis>
862  Show queue summary.
863  </synopsis>
864  <syntax>
865  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
866  <parameter name="Queue">
867  <para>Queue for which the summary is requested.</para>
868  </parameter>
869  </syntax>
870  <description>
871  <para>Request the manager to send a QueueSummary event.</para>
872  </description>
873  </manager>
874  <manager name="QueueAdd" language="en_US">
875  <synopsis>
876  Add interface to queue.
877  </synopsis>
878  <syntax>
879  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
880  <parameter name="Queue" required="true">
881  <para>Queue's name.</para>
882  </parameter>
883  <parameter name="Interface" required="true">
884  <para>The name of the interface (tech/name) to add to the queue.</para>
885  </parameter>
886  <parameter name="Penalty">
887  <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>
888  </parameter>
889  <parameter name="Paused">
890  <para>To pause or not the member initially (true/false or 1/0).</para>
891  </parameter>
892  <parameter name="MemberName">
893  <para>Text alias for the interface.</para>
894  </parameter>
895  <parameter name="StateInterface" />
896  </syntax>
897  <description>
898  </description>
899  </manager>
900  <manager name="QueueRemove" language="en_US">
901  <synopsis>
902  Remove interface from queue.
903  </synopsis>
904  <syntax>
905  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
906  <parameter name="Queue" required="true">
907  <para>The name of the queue to take action on.</para>
908  </parameter>
909  <parameter name="Interface" required="true">
910  <para>The interface (tech/name) to remove from queue.</para>
911  </parameter>
912  </syntax>
913  <description>
914  </description>
915  </manager>
916  <manager name="QueuePause" language="en_US">
917  <synopsis>
918  Makes a queue member temporarily unavailable.
919  </synopsis>
920  <syntax>
921  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
922  <parameter name="Interface" required="true">
923  <para>The name of the interface (tech/name) to pause or unpause.</para>
924  </parameter>
925  <parameter name="Paused" required="true">
926  <para>Pause or unpause the interface. Set to 'true' to pause the member or 'false' to unpause.</para>
927  </parameter>
928  <parameter name="Queue">
929  <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>
930  </parameter>
931  <parameter name="Reason">
932  <para>Text description, returned in the event QueueMemberPaused.</para>
933  </parameter>
934  </syntax>
935  <description>
936  <para>Pause or unpause a member in a queue.</para>
937  </description>
938  </manager>
939  <manager name="QueueLog" language="en_US">
940  <synopsis>
941  Adds custom entry in queue_log.
942  </synopsis>
943  <syntax>
944  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
945  <parameter name="Queue" required="true" />
946  <parameter name="Event" required="true" />
947  <parameter name="Uniqueid" />
948  <parameter name="Interface" />
949  <parameter name="Message" />
950  </syntax>
951  <description>
952  </description>
953  </manager>
954  <manager name="QueuePenalty" language="en_US">
955  <synopsis>
956  Set the penalty for a queue member.
957  </synopsis>
958  <syntax>
959  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
960  <parameter name="Interface" required="true">
961  <para>The interface (tech/name) of the member whose penalty to change.</para>
962  </parameter>
963  <parameter name="Penalty" required="true">
964  <para>The new penalty (number) for the member. Must be nonnegative.</para>
965  </parameter>
966  <parameter name="Queue">
967  <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>
968  </parameter>
969  </syntax>
970  <description>
971  <para>Change the penalty of a queue member</para>
972  </description>
973  </manager>
974  <manager name="QueueMemberRingInUse" language="en_US">
975  <synopsis>
976  Set the ringinuse value for a queue member.
977  </synopsis>
978  <syntax>
979  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
980  <parameter name="Interface" required="true" />
981  <parameter name="RingInUse" required="true" />
982  <parameter name="Queue" />
983  </syntax>
984  <description>
985  </description>
986  </manager>
987  <manager name="QueueRule" language="en_US">
988  <synopsis>
989  Queue Rules.
990  </synopsis>
991  <syntax>
992  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
993  <parameter name="Rule">
994  <para>The name of the rule in queuerules.conf whose contents to list.</para>
995  </parameter>
996  </syntax>
997  <description>
998  <para>List queue rules defined in queuerules.conf</para>
999  </description>
1000  </manager>
1001  <manager name="QueueReload" language="en_US">
1002  <synopsis>
1003  Reload a queue, queues, or any sub-section of a queue or queues.
1004  </synopsis>
1005  <syntax>
1006  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1007  <parameter name="Queue">
1008  <para>The name of the queue to take action on. If no queue name is specified, then all queues are affected.</para>
1009  </parameter>
1010  <parameter name="Members">
1011  <para>Whether to reload the queue's members.</para>
1012  <enumlist>
1013  <enum name="yes" />
1014  <enum name="no" />
1015  </enumlist>
1016  </parameter>
1017  <parameter name="Rules">
1018  <para>Whether to reload queuerules.conf</para>
1019  <enumlist>
1020  <enum name="yes" />
1021  <enum name="no" />
1022  </enumlist>
1023  </parameter>
1024  <parameter name="Parameters">
1025  <para>Whether to reload the other queue options.</para>
1026  <enumlist>
1027  <enum name="yes" />
1028  <enum name="no" />
1029  </enumlist>
1030  </parameter>
1031  </syntax>
1032  <description>
1033  </description>
1034  </manager>
1035  <manager name="QueueReset" language="en_US">
1036  <synopsis>
1037  Reset queue statistics.
1038  </synopsis>
1039  <syntax>
1040  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1041  <parameter name="Queue">
1042  <para>The name of the queue on which to reset statistics.</para>
1043  </parameter>
1044  </syntax>
1045  <description>
1046  <para>Reset the statistics for a queue.</para>
1047  </description>
1048  </manager>
1049  <manager name="QueueChangePriorityCaller" language="en_US">
1050  <synopsis>
1051  Change priority of a caller on queue.
1052  </synopsis>
1053  <syntax>
1054  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1055  <parameter name="Queue" required="true">
1056  <para>The name of the queue to take action on.</para>
1057  </parameter>
1058  <parameter name="Caller" required="true">
1059  <para>The caller (channel) to change priority on queue.</para>
1060  </parameter>
1061 
1062  <parameter name="Priority" required="true">
1063  <para>Priority value for change for caller on queue.</para>
1064  </parameter>
1065  </syntax>
1066  <description>
1067  </description>
1068  </manager>
1069  <manager name="QueueWithdrawCaller" language="en_US">
1070  <synopsis>
1071  Request to withdraw a caller from the queue back to the dialplan.
1072  </synopsis>
1073  <syntax>
1074  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1075  <parameter name="Queue" required="true">
1076  <para>The name of the queue to take action on.</para>
1077  </parameter>
1078  <parameter name="Caller" required="true">
1079  <para>The caller (channel) to withdraw from the queue.</para>
1080  </parameter>
1081  <parameter name="WithdrawInfo" required="false">
1082  <para>Optional info to store. If the call is successfully withdrawn from the queue, this information will be available in the QUEUE_WITHDRAW_INFO variable.</para>
1083  </parameter>
1084  </syntax>
1085  <description>
1086  </description>
1087  </manager>
1088 
1089  <managerEvent language="en_US" name="QueueParams">
1090  <managerEventInstance class="EVENT_FLAG_AGENT">
1091  <synopsis>Raised in response to the QueueStatus action.</synopsis>
1092  <syntax>
1093  <parameter name="Max">
1094  <para>The name of the queue.</para>
1095  </parameter>
1096  <parameter name="Strategy">
1097  <para>The strategy of the queue.</para>
1098  </parameter>
1099  <parameter name="Calls">
1100  <para>The queue member's channel technology or location.</para>
1101  </parameter>
1102  <parameter name="Holdtime">
1103  <para>The queue's hold time.</para>
1104  </parameter>
1105  <parameter name="TalkTime">
1106  <para>The queue's talk time.</para>
1107  </parameter>
1108  <parameter name="Completed">
1109  <para>The queue's completion time.</para>
1110  </parameter>
1111  <parameter name="Abandoned">
1112  <para>The queue's call abandonment metric.</para>
1113  </parameter>
1114  <parameter name="ServiceLevelPerf">
1115  <para>Primary service level performance metric.</para>
1116  </parameter>
1117  <parameter name="ServiceLevelPerf2">
1118  <para>Secondary service level performance metric.</para>
1119  </parameter>
1120  </syntax>
1121  <see-also>
1122  <ref type="managerEvent">QueueMember</ref>
1123  <ref type="managerEvent">QueueEntry</ref>
1124  </see-also>
1125  </managerEventInstance>
1126  </managerEvent>
1127  <managerEvent language="en_US" name="QueueEntry">
1128  <managerEventInstance class="EVENT_FLAG_AGENT">
1129  <synopsis>Raised in response to the QueueStatus action.</synopsis>
1130  <syntax>
1131  <parameter name="Queue">
1132  <para>The name of the queue.</para>
1133  </parameter>
1134  <parameter name="Position">
1135  <para>The caller's position within the queue.</para>
1136  </parameter>
1137  <parameter name="Channel">
1138  <para>The name of the caller's channel.</para>
1139  </parameter>
1140  <parameter name="Uniqueid">
1141  <para>The unique ID of the channel.</para>
1142  </parameter>
1143  <parameter name="CallerIDNum">
1144  <para>The Caller ID number.</para>
1145  </parameter>
1146  <parameter name="CallerIDName">
1147  <para>The Caller ID name.</para>
1148  </parameter>
1149  <parameter name="ConnectedLineNum">
1150  <para>The bridged party's number.</para>
1151  </parameter>
1152  <parameter name="ConnectedLineName">
1153  <para>The bridged party's name.</para>
1154  </parameter>
1155  <parameter name="Wait">
1156  <para>The caller's wait time.</para>
1157  </parameter>
1158  <parameter name="Priority">
1159  <para>The caller's priority within the queue.</para>
1160  </parameter>
1161  </syntax>
1162  <see-also>
1163  <ref type="managerEvent">QueueParams</ref>
1164  <ref type="managerEvent">QueueMember</ref>
1165  </see-also>
1166  </managerEventInstance>
1167  </managerEvent>
1168  <managerEvent language="en_US" name="QueueMemberStatus">
1169  <managerEventInstance class="EVENT_FLAG_AGENT">
1170  <synopsis>Raised when a Queue member's status has changed.</synopsis>
1171  <syntax>
1172  <parameter name="Queue">
1173  <para>The name of the queue.</para>
1174  </parameter>
1175  <parameter name="MemberName">
1176  <para>The name of the queue member.</para>
1177  </parameter>
1178  <parameter name="Interface">
1179  <para>The queue member's channel technology or location.</para>
1180  </parameter>
1181  <parameter name="StateInterface">
1182  <para>Channel technology or location from which to read device state changes.</para>
1183  </parameter>
1184  <parameter name="Membership">
1185  <enumlist>
1186  <enum name="dynamic"/>
1187  <enum name="realtime"/>
1188  <enum name="static"/>
1189  </enumlist>
1190  </parameter>
1191  <parameter name="Penalty">
1192  <para>The penalty associated with the queue member.</para>
1193  </parameter>
1194  <parameter name="CallsTaken">
1195  <para>The number of calls this queue member has serviced.</para>
1196  </parameter>
1197  <parameter name="LastCall">
1198  <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1199  </parameter>
1200  <parameter name="LastPause">
1201  <para>The time when started last paused the queue member.</para>
1202  </parameter>
1203  <parameter name="LoginTime">
1204  <para>The time this member logged in to the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1205  </parameter>
1206  <parameter name="InCall">
1207  <para>Set to 1 if member is in call. Set to 0 after LastCall time is updated.</para>
1208  <enumlist>
1209  <enum name="0"/>
1210  <enum name="1"/>
1211  </enumlist>
1212  </parameter>
1213  <parameter name="Status">
1214  <para>The numeric device state status of the queue member.</para>
1215  <enumlist>
1216  <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
1217  <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
1218  <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
1219  <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
1220  <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
1221  <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
1222  <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
1223  <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
1224  <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
1225  </enumlist>
1226  </parameter>
1227  <parameter name="Paused">
1228  <enumlist>
1229  <enum name="0"/>
1230  <enum name="1"/>
1231  </enumlist>
1232  </parameter>
1233  <parameter name="PausedReason">
1234  <para>If set when paused, the reason the queue member was paused.</para>
1235  </parameter>
1236  <parameter name="Ringinuse">
1237  <enumlist>
1238  <enum name="0"/>
1239  <enum name="1"/>
1240  </enumlist>
1241  </parameter>
1242  <parameter name="Wrapuptime">
1243  <para>The Wrapup Time of the queue member. If this value is set will override the wrapup time of queue.</para>
1244  </parameter>
1245  </syntax>
1246  </managerEventInstance>
1247  </managerEvent>
1248  <managerEvent language="en_US" name="QueueMemberAdded">
1249  <managerEventInstance class="EVENT_FLAG_AGENT">
1250  <synopsis>Raised when a member is added to the queue.</synopsis>
1251  <syntax>
1252  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1253  </syntax>
1254  <see-also>
1255  <ref type="managerEvent">QueueMemberRemoved</ref>
1256  <ref type="application">AddQueueMember</ref>
1257  </see-also>
1258  </managerEventInstance>
1259  </managerEvent>
1260  <managerEvent language="en_US" name="QueueMemberRemoved">
1261  <managerEventInstance class="EVENT_FLAG_AGENT">
1262  <synopsis>Raised when a member is removed from the queue.</synopsis>
1263  <syntax>
1264  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1265  </syntax>
1266  <see-also>
1267  <ref type="managerEvent">QueueMemberAdded</ref>
1268  <ref type="application">RemoveQueueMember</ref>
1269  </see-also>
1270  </managerEventInstance>
1271  </managerEvent>
1272  <managerEvent language="en_US" name="QueueMemberPause">
1273  <managerEventInstance class="EVENT_FLAG_AGENT">
1274  <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
1275  <syntax>
1276  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1277  </syntax>
1278  <see-also>
1279  <ref type="application">PauseQueueMember</ref>
1280  <ref type="application">UnPauseQueueMember</ref>
1281  </see-also>
1282  </managerEventInstance>
1283  </managerEvent>
1284  <managerEvent language="en_US" name="QueueMemberPenalty">
1285  <managerEventInstance class="EVENT_FLAG_AGENT">
1286  <synopsis>Raised when a member's penalty is changed.</synopsis>
1287  <syntax>
1288  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1289  </syntax>
1290  <see-also>
1291  <ref type="function">QUEUE_MEMBER</ref>
1292  </see-also>
1293  </managerEventInstance>
1294  </managerEvent>
1295  <managerEvent language="en_US" name="QueueMemberRinginuse">
1296  <managerEventInstance class="EVENT_FLAG_AGENT">
1297  <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
1298  <syntax>
1299  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1300  </syntax>
1301  <see-also>
1302  <ref type="function">QUEUE_MEMBER</ref>
1303  </see-also>
1304  </managerEventInstance>
1305  </managerEvent>
1306  <managerEvent language="en_US" name="QueueCallerJoin">
1307  <managerEventInstance class="EVENT_FLAG_AGENT">
1308  <synopsis>Raised when a caller joins a Queue.</synopsis>
1309  <syntax>
1310  <channel_snapshot/>
1311  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1312  <parameter name="Position">
1313  <para>This channel's current position in the queue.</para>
1314  </parameter>
1315  <parameter name="Count">
1316  <para>The total number of channels in the queue.</para>
1317  </parameter>
1318  </syntax>
1319  <see-also>
1320  <ref type="managerEvent">QueueCallerLeave</ref>
1321  <ref type="application">Queue</ref>
1322  </see-also>
1323  </managerEventInstance>
1324  </managerEvent>
1325  <managerEvent language="en_US" name="QueueCallerLeave">
1326  <managerEventInstance class="EVENT_FLAG_AGENT">
1327  <synopsis>Raised when a caller leaves a Queue.</synopsis>
1328  <syntax>
1329  <channel_snapshot/>
1330  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1331  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
1332  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1333  </syntax>
1334  <see-also>
1335  <ref type="managerEvent">QueueCallerJoin</ref>
1336  </see-also>
1337  </managerEventInstance>
1338  </managerEvent>
1339  <managerEvent language="en_US" name="QueueCallerAbandon">
1340  <managerEventInstance class="EVENT_FLAG_AGENT">
1341  <synopsis>Raised when a caller abandons the queue.</synopsis>
1342  <syntax>
1343  <channel_snapshot/>
1344  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1345  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1346  <parameter name="OriginalPosition">
1347  <para>The channel's original position in the queue.</para>
1348  </parameter>
1349  <parameter name="HoldTime">
1350  <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1351  </parameter>
1352  </syntax>
1353  </managerEventInstance>
1354  </managerEvent>
1355  <managerEvent language="en_US" name="AgentCalled">
1356  <managerEventInstance class="EVENT_FLAG_AGENT">
1357  <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
1358  <syntax>
1359  <channel_snapshot/>
1360  <channel_snapshot prefix="Dest"/>
1361  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1362  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1363  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1364  </syntax>
1365  <see-also>
1366  <ref type="managerEvent">AgentRingNoAnswer</ref>
1367  <ref type="managerEvent">AgentComplete</ref>
1368  <ref type="managerEvent">AgentConnect</ref>
1369  </see-also>
1370  </managerEventInstance>
1371  </managerEvent>
1372  <managerEvent language="en_US" name="AgentRingNoAnswer">
1373  <managerEventInstance class="EVENT_FLAG_AGENT">
1374  <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
1375  <syntax>
1376  <channel_snapshot/>
1377  <channel_snapshot prefix="Dest"/>
1378  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1379  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1380  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1381  <parameter name="RingTime">
1382  <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1383  </parameter>
1384  </syntax>
1385  <see-also>
1386  <ref type="managerEvent">AgentCalled</ref>
1387  </see-also>
1388  </managerEventInstance>
1389  </managerEvent>
1390  <managerEvent language="en_US" name="AgentComplete">
1391  <managerEventInstance class="EVENT_FLAG_AGENT">
1392  <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
1393  <syntax>
1394  <channel_snapshot/>
1395  <channel_snapshot prefix="Dest"/>
1396  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1397  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1398  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1399  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1400  <parameter name="TalkTime">
1401  <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1402  </parameter>
1403  <parameter name="Reason">
1404  <enumlist>
1405  <enum name="caller"/>
1406  <enum name="agent"/>
1407  <enum name="transfer"/>
1408  </enumlist>
1409  </parameter>
1410  </syntax>
1411  <see-also>
1412  <ref type="managerEvent">AgentCalled</ref>
1413  <ref type="managerEvent">AgentConnect</ref>
1414  </see-also>
1415  </managerEventInstance>
1416  </managerEvent>
1417  <managerEvent language="en_US" name="AgentDump">
1418  <managerEventInstance class="EVENT_FLAG_AGENT">
1419  <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
1420  <syntax>
1421  <channel_snapshot/>
1422  <channel_snapshot prefix="Dest"/>
1423  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1424  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1425  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1426  </syntax>
1427  <see-also>
1428  <ref type="managerEvent">AgentCalled</ref>
1429  <ref type="managerEvent">AgentConnect</ref>
1430  </see-also>
1431  </managerEventInstance>
1432  </managerEvent>
1433  <managerEvent language="en_US" name="AgentConnect">
1434  <managerEventInstance class="EVENT_FLAG_AGENT">
1435  <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
1436  <syntax>
1437  <channel_snapshot/>
1438  <channel_snapshot prefix="Dest"/>
1439  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1440  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1441  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1442  <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
1443  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1444  </syntax>
1445  <see-also>
1446  <ref type="managerEvent">AgentCalled</ref>
1447  <ref type="managerEvent">AgentComplete</ref>
1448  <ref type="managerEvent">AgentDump</ref>
1449  </see-also>
1450  </managerEventInstance>
1451  </managerEvent>
1452  ***/
1453 
1454 enum {
1456  OPT_GO_ON = (1 << 1),
1457  OPT_DATA_QUALITY = (1 << 2),
1458  OPT_CALLEE_GO_ON = (1 << 3),
1459  OPT_CALLEE_HANGUP = (1 << 4),
1460  OPT_CALLER_HANGUP = (1 << 5),
1463  OPT_CALLEE_PARK = (1 << 8),
1464  OPT_CALLER_PARK = (1 << 9),
1465  OPT_NO_RETRY = (1 << 10),
1466  OPT_RINGING = (1 << 11),
1468  OPT_CALLEE_TRANSFER = (1 << 13),
1469  OPT_CALLER_TRANSFER = (1 << 14),
1472  OPT_CALLEE_AUTOMON = (1 << 17),
1473  OPT_CALLER_AUTOMON = (1 << 18),
1474  OPT_PREDIAL_CALLEE = (1 << 19),
1475  OPT_PREDIAL_CALLER = (1 << 20),
1477 };
1478 
1479 enum {
1484  /* note: this entry _MUST_ be the last one in the enum */
1486 };
1487 
1492  AST_APP_OPTION('c', OPT_GO_ON),
1511 END_OPTIONS);
1512 
1513 enum {
1522 };
1523 
1524 enum {
1528 };
1529 
1534  QUEUE_RESET_STATS = (1 << 3),
1535 };
1536 
1537 static const struct strategy {
1539  const char *name;
1540 } strategies[] = {
1541  { QUEUE_STRATEGY_RINGALL, "ringall" },
1542  { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
1543  { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
1544  { QUEUE_STRATEGY_RANDOM, "random" },
1545  { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
1546  { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
1547  { QUEUE_STRATEGY_LINEAR, "linear" },
1548  { QUEUE_STRATEGY_WRANDOM, "wrandom"},
1549  { QUEUE_STRATEGY_RRORDERED, "rrordered"},
1550 };
1551 
1552 static const struct autopause {
1554  const char *name;
1555 } autopausesmodes [] = {
1556  { QUEUE_AUTOPAUSE_OFF,"no" },
1557  { QUEUE_AUTOPAUSE_ON, "yes" },
1558  { QUEUE_AUTOPAUSE_ALL,"all" },
1559 };
1560 
1561 #define DEFAULT_RETRY 5
1562 #define DEFAULT_TIMEOUT 15
1563 #define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
1564 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
1565 /*!
1566  * \brief The minimum number of seconds between position announcements.
1567  * \note The default value of 15 provides backwards compatibility.
1568  */
1569 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
1570 
1571 #define MAX_QUEUE_BUCKETS 53
1572 
1573 #define RES_OKAY 0 /*!< Action completed */
1574 #define RES_EXISTS (-1) /*!< Entry already exists */
1575 #define RES_OUTOFMEMORY (-2) /*!< Out of memory */
1576 #define RES_NOSUCHQUEUE (-3) /*!< No such queue */
1577 #define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
1578 #define RES_NOT_CALLER (-5) /*!< Caller not found */
1579 
1580 static char *app = "Queue";
1581 
1582 static char *app_aqm = "AddQueueMember" ;
1583 
1584 static char *app_rqm = "RemoveQueueMember" ;
1585 
1586 static char *app_pqm = "PauseQueueMember" ;
1587 
1588 static char *app_upqm = "UnpauseQueueMember" ;
1589 
1590 static char *app_ql = "QueueLog" ;
1591 
1592 static char *app_qupd = "QueueUpdate";
1593 
1594 /*! \brief Persistent Members astdb family */
1595 static const char * const pm_family = "Queue/PersistentMembers";
1596 
1597 /*! \brief queues.conf [general] option */
1599 
1600 /*! \brief Records that one or more queues use weight */
1601 static int use_weight;
1602 
1603 /*! \brief queues.conf [general] option */
1604 static int autofill_default;
1605 
1606 /*! \brief queues.conf [general] option */
1607 static int montype_default;
1608 
1609 /*! \brief queues.conf [general] option */
1610 static int shared_lastcall;
1611 
1612 /*! \brief queuerules.conf [general] option */
1613 static int realtime_rules;
1614 
1615 /*! \brief Subscription to device state change messages */
1617 
1618 /*! \brief queues.conf [general] option */
1620 
1621 /*! \brief queues.conf [general] option */
1623 
1624 /*! \brief name of the ringinuse field in the realtime database */
1626 
1637 };
1638 
1639 static const struct {
1640  enum queue_result id;
1641  char *text;
1642 } queue_results[] = {
1643  { QUEUE_UNKNOWN, "UNKNOWN" },
1644  { QUEUE_TIMEOUT, "TIMEOUT" },
1645  { QUEUE_JOINEMPTY,"JOINEMPTY" },
1646  { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
1647  { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
1648  { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
1649  { QUEUE_FULL, "FULL" },
1650  { QUEUE_CONTINUE, "CONTINUE" },
1651  { QUEUE_WITHDRAW, "WITHDRAW" },
1652 };
1653 
1657 };
1658 
1659 /*! \brief We define a custom "local user" structure because we
1660  * use it not only for keeping track of what is in use but
1661  * also for keeping track of who we're dialing.
1662  *
1663  * There are two "links" defined in this structure, q_next and call_next.
1664  * q_next links ALL defined callattempt structures into a linked list. call_next is
1665  * a link which allows for a subset of the callattempts to be traversed. This subset
1666  * is used in wait_for_answer so that irrelevant callattempts are not traversed. This
1667  * also is helpful so that queue logs are always accurate in the case where a call to
1668  * a member times out, especially if using the ringall strategy.
1669 */
1670 
1671 struct callattempt {
1675  char interface[256]; /*!< An Asterisk dial string (not a channel name) */
1676  int metric;
1677  struct member *member;
1678  /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
1680  /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
1682  /*! TRUE if the connected line update is blocked. */
1683  unsigned int block_connected_update:1;
1684  /*! TRUE if caller id is not available for connected line */
1685  unsigned int dial_callerid_absent:1;
1686  /*! TRUE if the call is still active */
1687  unsigned int stillgoing:1;
1689  /*! Original channel name. Must be freed. Could be NULL if allocation failed. */
1691 };
1692 
1693 
1694 struct queue_ent {
1695  struct call_queue *parent; /*!< What queue is our parent */
1696  char moh[MAX_MUSICCLASS]; /*!< Name of musiconhold to be used */
1697  char announce[PATH_MAX]; /*!< Announcement to play for member when call is answered */
1698  char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
1699  char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
1700  const char *predial_callee; /*!< Gosub app arguments for outgoing calls. NULL if not supplied. */
1701  int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
1702  int pos; /*!< Where we are in the queue */
1703  int prio; /*!< Our priority */
1704  int last_pos_said; /*!< Last position we told the user */
1705  int ring_when_ringing; /*!< Should we only use ring indication when a channel is ringing? */
1706  time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
1707  int last_periodic_announce_sound; /*!< The last periodic announcement we made */
1708  time_t last_pos; /*!< Last time we told the user their position */
1709  int opos; /*!< Where we started in the queue */
1710  int handled; /*!< Whether our call was handled */
1711  int pending; /*!< Non-zero if we are attempting to call a member */
1712  int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
1713  int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
1714  int raise_penalty; /*!< Float lower penalty members to a minimum penalty */
1715  int linpos; /*!< If using linear strategy, what position are we at? */
1716  int linwrapped; /*!< Is the linpos wrapped? */
1717  time_t start; /*!< When we started holding */
1718  time_t expire; /*!< When this entry should expire (time out of queue) */
1719  int cancel_answered_elsewhere; /*!< Whether we should force the CAE flag on this call (C) option*/
1720  unsigned int withdraw:1; /*!< Should this call exit the queue at its next iteration? Used for QueueWithdrawCaller */
1721  char *withdraw_info; /*!< Optional info passed by the caller of QueueWithdrawCaller */
1722  struct ast_channel *chan; /*!< Our channel */
1723  AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
1724  struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
1725  struct queue_ent *next; /*!< The next queue entry */
1726 };
1727 
1728 struct member {
1729  char interface[AST_CHANNEL_NAME]; /*!< Technology/Location to dial to reach this member*/
1730  char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
1731  char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
1732  char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
1733  int state_id; /*!< Extension state callback id (if using hint) */
1734  char membername[80]; /*!< Member name to use in queue logs */
1735  int penalty; /*!< Are we a last resort? */
1736  int calls; /*!< Number of calls serviced by this member */
1737  int dynamic; /*!< Are we dynamically added? */
1738  int realtime; /*!< Is this member realtime? */
1739  int status; /*!< Status of queue member */
1740  int paused; /*!< Are we paused (not accepting calls)? */
1741  char reason_paused[80]; /*!< Reason of paused if member is paused */
1742  int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */
1743  int callcompletedinsl; /*!< Whether the current call was completed within service level */
1744  int wrapuptime; /*!< Wrapup Time */
1745  time_t starttime; /*!< The time at which the member answered the current caller. */
1746  time_t lastcall; /*!< When last successful call was hungup */
1747  time_t lastpause; /*!< When started the last pause */
1748  time_t logintime; /*!< The time when started the login */
1749  struct call_queue *lastqueue; /*!< Last queue we received a call */
1750  unsigned int dead:1; /*!< Used to detect members deleted in realtime */
1751  unsigned int delme:1; /*!< Flag to delete entry on reload */
1752  char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
1753  unsigned int ringinuse:1; /*!< Flag to ring queue members even if their status is 'inuse' */
1754 };
1755 
1759  QUEUE_EMPTY_INUSE = (1 << 2),
1765 };
1766 
1770 };
1771 
1772 /* values used in multi-bit flags in call_queue */
1773 #define ANNOUNCEHOLDTIME_ALWAYS 1
1774 #define ANNOUNCEHOLDTIME_ONCE 2
1775 #define QUEUE_EVENT_VARIABLES 3
1776 
1778  int time; /*!< Number of seconds that need to pass before applying this rule */
1779  int max_value; /*!< The amount specified in the penalty rule for max penalty */
1780  int min_value; /*!< The amount specified in the penalty rule for min penalty */
1781  int raise_value; /*!< The amount specified in the penalty rule for min penalty */
1782  int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
1783  int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
1784  int raise_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
1785  AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
1786 };
1787 
1788 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
1789 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
1790 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
1791 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
1792 
1793 struct call_queue {
1795  /*! Queue name */
1797  /*! Music on Hold class */
1799  /*! Announcement to play when call is answered */
1801  /*! Exit context */
1803  /*! Macro to run upon member connection */
1805  /*! Gosub to run upon member connection */
1807  /*! Default rule to use if none specified in call to Queue() */
1809  /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
1811  /*! Sound file: "There are currently" (def. queue-thereare) */
1813  /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
1815  /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
1817  /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
1819  /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
1821  /*! Sound file: "minutes." (def. queue-minutes) */
1823  /*! Sound file: "minute." (def. queue-minute) */
1825  /*! Sound file: "seconds." (def. queue-seconds) */
1827  /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
1829  /*! Sound file: Custom announce for caller, no default */
1831  /*! Sound file: "Hold time" (def. queue-reporthold) */
1833  );
1834  /*! Sound files: Custom announce, no default */
1836  unsigned int dead:1;
1837  unsigned int ringinuse:1;
1838  unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
1839  unsigned int setinterfacevar:1;
1840  unsigned int setqueuevar:1;
1841  unsigned int setqueueentryvar:1;
1842  unsigned int reportholdtime:1;
1843  unsigned int wrapped:1;
1844  unsigned int timeoutrestart:1;
1845  unsigned int announceholdtime:2;
1846  unsigned int announceposition:3;
1847  unsigned int announceposition_only_up:1; /*!< Only announce position if it has improved */
1848  int strategy:4;
1849  unsigned int realtime:1;
1850  unsigned int found:1;
1852  unsigned int autopausebusy:1;
1853  unsigned int autopauseunavail:1;
1856  int announcepositionlimit; /*!< How many positions we announce? */
1857  int announcefrequency; /*!< How often to announce their position */
1858  int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
1859  int periodicannouncefrequency; /*!< How often to play periodic announcement */
1860  int numperiodicannounce; /*!< The number of periodic announcements configured */
1861  int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
1862  int roundingseconds; /*!< How many seconds do we round to? */
1863  int holdtime; /*!< Current avg holdtime, based on an exponential average */
1864  int talktime; /*!< Current avg talktime, based on the same exponential average */
1865  int callscompleted; /*!< Number of queue calls completed */
1866  int callsabandoned; /*!< Number of queue calls abandoned */
1867  int callsabandonedinsl; /*!< Number of queue calls abandoned in servicelevel */
1868  int servicelevel; /*!< seconds setting for servicelevel*/
1869  int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
1870  char monfmt[8]; /*!< Format to use when recording calls */
1871  int montype; /*!< Monitor type Monitor vs. MixMonitor */
1872  int count; /*!< How many entries */
1873  int maxlen; /*!< Max number of entries */
1874  int wrapuptime; /*!< Wrapup Time */
1875  int penaltymemberslimit; /*!< Disregard penalty when queue has fewer than this many members */
1876 
1877  int retry; /*!< Retry calling everyone after this amount of time */
1878  int timeout; /*!< How long to wait for an answer */
1879  int weight; /*!< Respective weight */
1880  int autopause; /*!< Auto pause queue members if they fail to answer */
1881  int autopausedelay; /*!< Delay auto pause for autopausedelay seconds since last call */
1882  int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
1883 
1884  /* Queue strategy things */
1885  int rrpos; /*!< Round Robin - position */
1886  int memberdelay; /*!< Seconds to delay connecting member to caller */
1887  int autofill; /*!< Ignore the head call status and ring an available agent */
1888 
1889  struct ao2_container *members; /*!< Head of the list of members */
1890  struct queue_ent *head; /*!< Head of the list of callers */
1891  AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
1892  AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
1893 };
1894 
1895 struct rule_list {
1896  char name[80];
1899 };
1900 
1902 
1903 static struct ao2_container *queues;
1904 
1905 static void update_realtime_members(struct call_queue *q);
1906 static struct member *interface_exists(struct call_queue *q, const char *interface);
1907 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
1908 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime);
1909 
1910 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
1911 /*! \brief sets the QUEUESTATUS channel variable */
1912 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
1913 {
1914  int i;
1915 
1916  for (i = 0; i < ARRAY_LEN(queue_results); i++) {
1917  if (queue_results[i].id == res) {
1918  pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
1919  return;
1920  }
1921  }
1922 }
1923 
1924 static const char *int2strat(int strategy)
1925 {
1926  int x;
1927 
1928  for (x = 0; x < ARRAY_LEN(strategies); x++) {
1929  if (strategy == strategies[x].strategy) {
1930  return strategies[x].name;
1931  }
1932  }
1933 
1934  return "<unknown>";
1935 }
1936 
1937 static int strat2int(const char *strategy)
1938 {
1939  int x;
1940 
1941  for (x = 0; x < ARRAY_LEN(strategies); x++) {
1942  if (!strcasecmp(strategy, strategies[x].name)) {
1943  return strategies[x].strategy;
1944  }
1945  }
1946 
1947  return -1;
1948 }
1949 
1950 static int autopause2int(const char *autopause)
1951 {
1952  int x;
1953  /*This 'double check' that default value is OFF */
1954  if (ast_strlen_zero(autopause)) {
1955  return QUEUE_AUTOPAUSE_OFF;
1956  }
1957 
1958  /*This 'double check' is to ensure old values works */
1959  if(ast_true(autopause)) {
1960  return QUEUE_AUTOPAUSE_ON;
1961  }
1962 
1963  for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1964  if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1965  return autopausesmodes[x].autopause;
1966  }
1967  }
1968 
1969  /*This 'double check' that default value is OFF */
1970  return QUEUE_AUTOPAUSE_OFF;
1971 }
1972 
1973 static int queue_hash_cb(const void *obj, const int flags)
1974 {
1975  const struct call_queue *q = obj;
1976 
1977  return ast_str_case_hash(q->name);
1978 }
1979 
1980 static int queue_cmp_cb(void *obj, void *arg, int flags)
1981 {
1982  struct call_queue *q = obj, *q2 = arg;
1983  return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1984 }
1985 
1986 /*!
1987  * \brief Return wrapuptime
1988  *
1989  * This function checks if wrapuptime in member is set and return this value.
1990  * Otherwise return value the wrapuptime in the queue configuration
1991  * \return integer value
1992  */
1993 static int get_wrapuptime(struct call_queue *q, struct member *member)
1994 {
1995  if (member->wrapuptime) {
1996  return member->wrapuptime;
1997  }
1998  return q->wrapuptime;
1999 }
2000 
2001 /*! \internal
2002  * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
2003  * \param obj the member being acted on
2004  * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
2005  * \param flag unused
2006  */
2007 static int queue_member_decrement_followers(void *obj, void *arg, int flag)
2008 {
2009  struct member *mem = obj;
2010  int *decrement_followers_after = arg;
2011 
2012  if (mem->queuepos > *decrement_followers_after) {
2013  mem->queuepos--;
2014  }
2015 
2016  return 0;
2017 }
2018 
2019 /*! \internal
2020  * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
2021  * on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
2022  * \param obj member being acted on
2023  * \param arg pointer to the queue members are being removed from
2024  * \param flag unused
2025  */
2026 static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
2027 {
2028  struct member *mem = obj;
2029  struct call_queue *queue = arg;
2030  int rrpos = mem->queuepos;
2031 
2032  if (mem->delme) {
2034  }
2035 
2036  return 0;
2037 }
2038 
2039 /*! \internal
2040  * \brief Use this to decrement followers during removal of a member
2041  * \param queue which queue the member is being removed from
2042  * \param mem which member is being removed from the queue
2043  */
2044 static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
2045 {
2046  int pos = mem->queuepos;
2047 
2048  /* 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
2049  * who would have been next otherwise. */
2050  if (pos < queue->rrpos) {
2051  queue->rrpos--;
2052  }
2053 
2055 }
2056 
2057 #define queue_ref(q) ao2_bump(q)
2058 #define queue_unref(q) ({ ao2_cleanup(q); NULL; })
2059 #define queue_t_ref(q, tag) ao2_t_bump(q, tag)
2060 #define queue_t_unref(q, tag) ({ ao2_t_cleanup(q, tag); NULL; })
2061 #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
2062 #define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
2063 
2064 /*! \brief Set variables of queue */
2065 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
2066 {
2067  char interfacevar[256]="";
2068  float sl = 0;
2069 
2070  ao2_lock(q);
2071 
2072  if (q->setqueuevar) {
2073  sl = 0;
2074  if (q->callscompleted > 0) {
2075  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
2076  }
2077 
2078  snprintf(interfacevar, sizeof(interfacevar),
2079  "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
2080  q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
2081 
2082  ao2_unlock(q);
2083 
2084  pbx_builtin_setvar_multiple(chan, interfacevar);
2085  } else {
2086  ao2_unlock(q);
2087  }
2088 }
2089 
2090 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
2091 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
2092 {
2093  struct queue_ent *cur;
2094 
2095  if (!q || !new)
2096  return;
2097  if (prev) {
2098  cur = prev->next;
2099  prev->next = new;
2100  } else {
2101  cur = q->head;
2102  q->head = new;
2103  }
2104  new->next = cur;
2105 
2106  /* every queue_ent must have a reference to it's parent call_queue, this
2107  * reference does not go away until the end of the queue_ent's life, meaning
2108  * that even when the queue_ent leaves the call_queue this ref must remain. */
2109  queue_ref(q);
2110  new->parent = q;
2111  new->pos = ++(*pos);
2112  new->opos = *pos;
2113 }
2114 
2116 {
2118  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
2119  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2120 
2121  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
2122  event_string = ast_manager_str_from_json_object(obj->blob, NULL);
2123  if (!channel_string || !event_string) {
2124  return NULL;
2125  }
2126 
2128  "%s"
2129  "%s",
2130  ast_str_buffer(channel_string),
2131  ast_str_buffer(event_string));
2132 }
2133 
2135 {
2136  return queue_channel_to_ami("QueueCallerJoin", message);
2137 }
2138 
2140 {
2141  return queue_channel_to_ami("QueueCallerLeave", message);
2142 }
2143 
2145 {
2146  return queue_channel_to_ami("QueueCallerAbandon", message);
2147 }
2148 
2149 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_join_type,
2151  );
2152 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_leave_type,
2154  );
2155 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_abandon_type,
2157  );
2158 
2160 {
2161  struct ast_json_payload *payload = stasis_message_data(message);
2162  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2163 
2164  event_string = ast_manager_str_from_json_object(payload->json, NULL);
2165  if (!event_string) {
2166  return NULL;
2167  }
2168 
2170  "%s",
2171  ast_str_buffer(event_string));
2172 }
2173 
2175 {
2176  return queue_member_to_ami("QueueMemberStatus", message);
2177 }
2178 
2180 {
2181  return queue_member_to_ami("QueueMemberAdded", message);
2182 }
2183 
2185 {
2186  return queue_member_to_ami("QueueMemberRemoved", message);
2187 }
2188 
2190 {
2191  return queue_member_to_ami("QueueMemberPause", message);
2192 }
2193 
2195 {
2196  return queue_member_to_ami("QueueMemberPenalty", message);
2197 }
2198 
2200 {
2201  return queue_member_to_ami("QueueMemberRinginuse", message);
2202 }
2203 
2204 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_status_type,
2206  );
2207 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_added_type,
2209  );
2210 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_removed_type,
2212  );
2213 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_pause_type,
2215  );
2216 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_penalty_type,
2218  );
2219 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_ringinuse_type,
2221  );
2222 
2224 {
2226  struct ast_channel_snapshot *caller;
2227  struct ast_channel_snapshot *agent;
2228  RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
2229  RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
2230  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2231 
2232  caller = ast_multi_channel_blob_get_channel(obj, "caller");
2233  if (caller) {
2234  caller_event_string = ast_manager_build_channel_state_string(caller);
2235  if (!caller_event_string) {
2236  ast_log(LOG_NOTICE, "No caller event string, bailing\n");
2237  return NULL;
2238  }
2239  }
2240 
2241  agent = ast_multi_channel_blob_get_channel(obj, "agent");
2242  if (agent) {
2243  agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
2244  if (!agent_event_string) {
2245  ast_log(LOG_NOTICE, "No agent event string, bailing\n");
2246  return NULL;
2247  }
2248  }
2249 
2251  if (!event_string) {
2252  return NULL;
2253  }
2254 
2256  "%s"
2257  "%s"
2258  "%s",
2259  caller_event_string ? ast_str_buffer(caller_event_string) : "",
2260  agent_event_string ? ast_str_buffer(agent_event_string) : "",
2261  ast_str_buffer(event_string));
2262 }
2263 
2265 {
2266  return queue_multi_channel_to_ami("AgentCalled", message);
2267 }
2268 
2270 {
2271  return queue_multi_channel_to_ami("AgentConnect", message);
2272 }
2273 
2275 {
2276  return queue_multi_channel_to_ami("AgentComplete", message);
2277 }
2278 
2280 {
2281  return queue_multi_channel_to_ami("AgentDump", message);
2282 }
2283 
2285 {
2286  return queue_multi_channel_to_ami("AgentRingNoAnswer", message);
2287 }
2288 
2289 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_called_type,
2291  );
2292 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_connect_type,
2294  );
2295 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_complete_type,
2297  );
2298 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_dump_type,
2300  );
2301 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_ringnoanswer_type,
2303  );
2304 
2306  struct ast_channel_snapshot *caller_snapshot,
2307  struct ast_channel_snapshot *agent_snapshot,
2308  struct stasis_message_type *type, struct ast_json *blob)
2309 {
2310  RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
2311  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
2312 
2313  if (!type) {
2314  return;
2315  }
2316 
2317  payload = ast_multi_channel_blob_create(blob);
2318  if (!payload) {
2319  return;
2320  }
2321 
2322  if (caller_snapshot) {
2323  ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
2324  } else {
2325  ast_debug(1, "Empty caller_snapshot; sending incomplete event\n");
2326  }
2327 
2328  if (agent_snapshot) {
2329  ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
2330  }
2331 
2332  msg = stasis_message_create(type, payload);
2333  if (!msg) {
2334  return;
2335  }
2336 
2337  stasis_publish(topic, msg);
2338 }
2339 
2340 static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent,
2341  struct stasis_message_type *type, struct ast_json *blob)
2342 {
2343  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
2344  RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
2345 
2346  ast_channel_lock(caller);
2347  caller_snapshot = ast_channel_snapshot_create(caller);
2348  ast_channel_unlock(caller);
2349  ast_channel_lock(agent);
2350  agent_snapshot = ast_channel_snapshot_create(agent);
2351  ast_channel_unlock(agent);
2352 
2353  if (!caller_snapshot || !agent_snapshot) {
2354  return;
2355  }
2356 
2358  agent_snapshot, type, blob);
2359 }
2360 
2361 /*!
2362  * \internal
2363  * \brief Publish the member blob.
2364  * \since 12.0.0
2365  *
2366  * \param type Stasis message type to publish.
2367  * \param blob The information being published.
2368  *
2369  * \note The json blob reference is passed to this function.
2370  */
2372 {
2373  RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
2374  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
2375 
2376  if (!blob || !type) {
2377  ast_json_unref(blob);
2378  return;
2379  }
2380 
2381  payload = ast_json_payload_create(blob);
2382  ast_json_unref(blob);
2383  if (!payload) {
2384  return;
2385  }
2386 
2387  msg = stasis_message_create(type, payload);
2388  if (!msg) {
2389  return;
2390  }
2391 
2393 }
2394 
2395 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
2396 {
2397  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: i, s: s, s: i, s: i}",
2398  "Queue", q->name,
2399  "MemberName", mem->membername,
2400  "Interface", mem->interface,
2401  "StateInterface", mem->state_interface,
2402  "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
2403  "Penalty", mem->penalty,
2404  "CallsTaken", mem->calls,
2405  "LastCall", (int)mem->lastcall,
2406  "LastPause", (int)mem->lastpause,
2407  "LoginTime", (int)mem->logintime,
2408  "InCall", mem->starttime ? 1 : 0,
2409  "Status", mem->status,
2410  "Paused", mem->paused,
2411  "PausedReason", mem->reason_paused,
2412  "Ringinuse", mem->ringinuse,
2413  "Wrapuptime", mem->wrapuptime);
2414 }
2415 
2416 /*! \brief Check if members are available
2417  *
2418  * This function checks to see if members are available to be called. If any member
2419  * is available, the function immediately returns 0. If no members are available,
2420  * then -1 is returned.
2421  */
2422 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, int raise_penalty, enum empty_conditions conditions, int devstate)
2423 {
2424  struct member *member;
2425  struct ao2_iterator mem_iter;
2426 
2427  ao2_lock(q);
2428  mem_iter = ao2_iterator_init(q->members, 0);
2429  for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
2430  int penalty = member->penalty;
2431  if (raise_penalty != INT_MAX && penalty < raise_penalty) {
2432  ast_debug(4, "%s is having his penalty raised up from %d to %d\n", member->membername, penalty, raise_penalty);
2433  penalty = raise_penalty;
2434  }
2435  if ((max_penalty != INT_MAX && penalty > max_penalty) || (min_penalty != INT_MAX && penalty < min_penalty)) {
2436  if (conditions & QUEUE_EMPTY_PENALTY) {
2437  ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
2438  continue;
2439  }
2440  }
2441 
2442  switch (devstate ? ast_device_state(member->state_interface) : member->status) {
2443  case AST_DEVICE_INVALID:
2444  if (conditions & QUEUE_EMPTY_INVALID) {
2445  ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
2446  break;
2447  }
2448  goto default_case;
2450  if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
2451  ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
2452  break;
2453  }
2454  goto default_case;
2455  case AST_DEVICE_INUSE:
2456  if (conditions & QUEUE_EMPTY_INUSE) {
2457  ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
2458  break;
2459  }
2460  goto default_case;
2461  case AST_DEVICE_RINGING:
2462  if (conditions & QUEUE_EMPTY_RINGING) {
2463  ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
2464  break;
2465  }
2466  goto default_case;
2467  case AST_DEVICE_UNKNOWN:
2468  if (conditions & QUEUE_EMPTY_UNKNOWN) {
2469  ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
2470  break;
2471  }
2472  /* Fall-through */
2473  default:
2474  default_case:
2475  if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
2476  ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
2477  break;
2478  } else if ((conditions & QUEUE_EMPTY_WRAPUP)
2479  && member->lastcall
2480  && get_wrapuptime(q, member)
2481  && (time(NULL) - get_wrapuptime(q, member) < member->lastcall)) {
2482  ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n",
2483  member->membername, (int) (time(NULL) - member->lastcall), get_wrapuptime(q, member));
2484  break;
2485  } else {
2486  ao2_ref(member, -1);
2487  ao2_iterator_destroy(&mem_iter);
2488  ao2_unlock(q);
2489  ast_debug(4, "%s is available.\n", member->membername);
2490  return 0;
2491  }
2492  break;
2493  }
2494  }
2495  ao2_iterator_destroy(&mem_iter);
2496  ao2_unlock(q);
2497 
2498  if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
2499  /* member state still may be RINGING due to lag in event message - check again with device state */
2500  return get_member_status(q, max_penalty, min_penalty, raise_penalty, conditions, 1);
2501  }
2502  return -1;
2503 }
2504 
2505 /*
2506  * A "pool" of member objects that calls are currently pending on. If an
2507  * agent is a member of multiple queues it's possible for that agent to be
2508  * called by each of the queues at the same time. This happens because device
2509  * state is slow to notify the queue app of one of it's member's being rung.
2510  * This "pool" allows us to track which members are currently being rung while
2511  * we wait on the device state change.
2512  */
2514 #define MAX_CALL_ATTEMPT_BUCKETS 353
2515 
2516 static int pending_members_hash(const void *obj, const int flags)
2517 {
2518  const struct member *object;
2519  const char *key;
2520 
2521  switch (flags & OBJ_SEARCH_MASK) {
2522  case OBJ_SEARCH_KEY:
2523  key = obj;
2524  break;
2525  case OBJ_SEARCH_OBJECT:
2526  object = obj;
2527  key = object->interface;
2528  break;
2529  default:
2530  ast_assert(0);
2531  return 0;
2532  }
2533  return ast_str_case_hash(key);
2534 }
2535 
2536 static int pending_members_cmp(void *obj, void *arg, int flags)
2537 {
2538  const struct member *object_left = obj;
2539  const struct member *object_right = arg;
2540  const char *right_key = arg;
2541  int cmp;
2542 
2543  switch (flags & OBJ_SEARCH_MASK) {
2544  case OBJ_SEARCH_OBJECT:
2545  right_key = object_right->interface;
2546  /* Fall through */
2547  case OBJ_SEARCH_KEY:
2548  cmp = strcasecmp(object_left->interface, right_key);
2549  break;
2551  /* Not supported by container. */
2552  ast_assert(0);
2553  return 0;
2554  default:
2555  cmp = 0;
2556  break;
2557  }
2558  if (cmp) {
2559  return 0;
2560  }
2561  return CMP_MATCH;
2562 }
2563 
2564 static void pending_members_remove(struct member *mem)
2565 {
2566  ast_debug(3, "Removed %s from pending_members\n", mem->membername);
2568 }
2569 
2570 /*! \brief set a member's status based on device state of that member's state_interface.
2571  *
2572  * Lock interface list find sc, iterate through each queues queue_member list for member to
2573  * update state inside queues
2574 */
2575 static void update_status(struct call_queue *q, struct member *m, const int status)
2576 {
2577  if (m->status != status) {
2578  /* If this member has transitioned to being available then update their queue
2579  * information. If they are currently in a call then the leg to the agent will be
2580  * considered done and the call finished.
2581  */
2582  if (status == AST_DEVICE_NOT_INUSE) {
2584  }
2585 
2586  m->status = status;
2587 
2588  /* Remove the member from the pending members pool only when the status changes.
2589  * This is not done unconditionally because we can occasionally see multiple
2590  * device state notifications of not in use after a previous call has ended,
2591  * including after we have initiated a new call. This is more likely to
2592  * happen when there is latency in the connection to the member.
2593  */
2595 
2596  queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
2597  }
2598 }
2599 
2600 /*!
2601  * \internal
2602  * \brief Determine if a queue member is available
2603  * \retval 1 if the member is available
2604  * \retval 0 if the member is not available
2605  */
2606 static int is_member_available(struct call_queue *q, struct member *mem)
2607 {
2608  int available = 0;
2609  int wrapuptime;
2610 
2611  switch (mem->status) {
2612  case AST_DEVICE_INVALID:
2614  break;
2615  case AST_DEVICE_INUSE:
2616  case AST_DEVICE_BUSY:
2617  case AST_DEVICE_RINGING:
2618  case AST_DEVICE_RINGINUSE:
2619  case AST_DEVICE_ONHOLD:
2620  if (!mem->ringinuse) {
2621  break;
2622  }
2623  /* else fall through */
2624  case AST_DEVICE_NOT_INUSE:
2625  case AST_DEVICE_UNKNOWN:
2626  if (!mem->paused) {
2627  available = 1;
2628  }
2629  break;
2630  }
2631 
2632  /* Let wrapuptimes override device state availability */
2633  wrapuptime = get_wrapuptime(q, mem);
2634  if (mem->lastcall && wrapuptime && (time(NULL) - wrapuptime < mem->lastcall)) {
2635  available = 0;
2636  }
2637  return available;
2638 }
2639 
2640 /*! \brief set a member's status based on device state of that member's interface*/
2641 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
2642 {
2643  struct ao2_iterator miter, qiter;
2644  struct ast_device_state_message *dev_state;
2645  struct member *m;
2646  struct call_queue *q;
2647  char interface[80], *slash_pos;
2648  int found = 0; /* Found this member in any queue */
2649  int found_member; /* Found this member in this queue */
2650  int avail = 0; /* Found an available member in this queue */
2651 
2653  return;
2654  }
2655 
2656  dev_state = stasis_message_data(msg);
2657  if (dev_state->eid) {
2658  /* ignore non-aggregate states */
2659  return;
2660  }
2661 
2662  qiter = ao2_iterator_init(queues, 0);
2663  while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2664  ao2_lock(q);
2665 
2666  avail = 0;
2667  found_member = 0;
2668  miter = ao2_iterator_init(q->members, 0);
2669  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2670  if (!found_member) {
2671  ast_copy_string(interface, m->state_interface, sizeof(interface));
2672 
2673  if ((slash_pos = strchr(interface, '/'))) {
2674  if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2675  *slash_pos = '\0';
2676  }
2677  }
2678 
2679  if (!strcasecmp(interface, dev_state->device)) {
2680  found_member = 1;
2681  update_status(q, m, dev_state->state);
2682  }
2683  }
2684 
2685  /* check every member until we find one NOT_INUSE */
2686  if (!avail) {
2687  avail = is_member_available(q, m);
2688  }
2689  if (avail && found_member) {
2690  /* early exit as we've found an available member and the member of interest */
2691  ao2_ref(m, -1);
2692  break;
2693  }
2694  }
2695 
2696  if (found_member) {
2697  found = 1;
2698  if (avail) {
2700  } else {
2702  }
2703  }
2704 
2705  ao2_iterator_destroy(&miter);
2706 
2707  ao2_unlock(q);
2708  queue_t_unref(q, "Done with iterator");
2709  }
2710  ao2_iterator_destroy(&qiter);
2711 
2712  if (found) {
2713  ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
2714  dev_state->device,
2715  dev_state->state,
2716  ast_devstate2str(dev_state->state));
2717  } else {
2718  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",
2719  dev_state->device,
2720  dev_state->state,
2721  ast_devstate2str(dev_state->state));
2722  }
2723 
2724  return;
2725 }
2726 
2727 /*! \brief Helper function which converts from extension state to device state values */
2729 {
2730  switch (state) {
2733  break;
2734  case AST_EXTENSION_INUSE:
2736  break;
2737  case AST_EXTENSION_BUSY:
2739  break;
2740  case AST_EXTENSION_RINGING:
2742  break;
2745  break;
2746  case AST_EXTENSION_ONHOLD:
2748  break;
2751  break;
2754  break;
2755  case AST_EXTENSION_REMOVED:
2757  default:
2759  break;
2760  }
2761 
2762  return state;
2763 }
2764 
2765 /*!
2766  * \brief Returns if one context includes another context
2767  *
2768  * \param parent Parent context to search for child
2769  * \param child Context to check for inclusion in parent
2770  *
2771  * This function recursively checks if the context child is included in the context parent.
2772  *
2773  * \retval 1 if child is included in parent
2774  * \retval 0 if not
2775  */
2776 static int context_included(const char *parent, const char *child);
2777 static int context_included(const char *parent, const char *child)
2778 {
2779  struct ast_context *c = NULL;
2780 
2781  c = ast_context_find(parent);
2782  if (!c) {
2783  /* well, if parent doesn't exist, how can the child be included in it? */
2784  return 0;
2785  }
2786  if (!strcmp(ast_get_context_name(c), parent)) {
2787  /* found the context of the hint app_queue is using. Now, see
2788  if that context includes the one that just changed state */
2789  struct ast_include *inc = NULL;
2790 
2791  while ((inc = (struct ast_include*) ast_walk_context_includes(c, inc))) {
2792  const char *includename = ast_get_include_name(inc);
2793  if (!strcasecmp(child, includename)) {
2794  return 1;
2795  }
2796  /* recurse on this context, for nested includes. The
2797  PBX extension parser will prevent infinite recursion. */
2798  if (context_included(includename, child)) {
2799  return 1;
2800  }
2801  }
2802  }
2803  return 0;
2804 }
2805 
2806 static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
2807 {
2808  struct ao2_iterator miter, qiter;
2809  struct member *m;
2810  struct call_queue *q;
2811  int state = info->exten_state;
2812  int found = 0, device_state = extensionstate2devicestate(state);
2813 
2814  /* only interested in extension state updates involving device states */
2815  if (info->reason != AST_HINT_UPDATE_DEVICE) {
2816  return 0;
2817  }
2818 
2819  qiter = ao2_iterator_init(queues, 0);
2820  while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2821  ao2_lock(q);
2822 
2823  miter = ao2_iterator_init(q->members, 0);
2824  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2825  if (!strcmp(m->state_exten, exten) &&
2826  (!strcmp(m->state_context, context) || context_included(m->state_context, context))) {
2827  /* context could be included in m->state_context. We need to check. */
2828  found = 1;
2829  update_status(q, m, device_state);
2830  }
2831  }
2832  ao2_iterator_destroy(&miter);
2833 
2834  ao2_unlock(q);
2835  queue_t_unref(q, "Done with iterator");
2836  }
2837  ao2_iterator_destroy(&qiter);
2838 
2839  if (found) {
2840  ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2841  } else {
2842  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",
2843  exten, context, device_state, ast_devstate2str(device_state));
2844  }
2845 
2846  return 0;
2847 }
2848 
2849 /*! \brief Return the current state of a member */
2850 static int get_queue_member_status(struct member *cur)
2851 {
2853 }
2854 
2855 static void destroy_queue_member_cb(void *obj)
2856 {
2857  struct member *mem = obj;
2858 
2859  if (mem->state_id != -1) {
2861  }
2862 }
2863 
2864 /*! \brief allocate space for new queue member and set fields based on parameters passed */
2865 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse, int wrapuptime)
2866 {
2867  struct member *cur;
2868 
2869  if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
2870  cur->ringinuse = ringinuse;
2871  cur->penalty = penalty;
2872  cur->paused = paused;
2873  cur->wrapuptime = wrapuptime;
2874  if (paused) {
2875  time(&cur->lastpause); /* Update time of last pause */
2876  }
2877  time(&cur->logintime);
2878  ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2881  } else {
2883  }
2884  if (!ast_strlen_zero(membername)) {
2885  ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2886  } else {
2887  ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2888  }
2889  if (!strchr(cur->interface, '/')) {
2890  ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2891  }
2892  if (!strncmp(cur->state_interface, "hint:", 5)) {
2893  char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2894  char *exten = strsep(&context, "@") + 5;
2895 
2896  ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2897  ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2898 
2900  } else {
2901  cur->state_id = -1;
2902  }
2903  cur->status = get_queue_member_status(cur);
2904  }
2905 
2906  return cur;
2907 }
2908 
2909 
2910 static int compress_char(const char c)
2911 {
2912  if (c < 32) {
2913  return 0;
2914  } else if (c > 96) {
2915  return c - 64;
2916  }
2917  return c - 32;
2918 }
2919 
2920 static int member_hash_fn(const void *obj, const int flags)
2921 {
2922  const struct member *mem = obj;
2923  const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
2924  const char *chname = strchr(interface, '/');
2925  int ret = 0, i;
2926 
2927  if (!chname) {
2928  chname = interface;
2929  }
2930  for (i = 0; i < 5 && chname[i]; i++) {
2931  ret += compress_char(chname[i]) << (i * 6);
2932  }
2933  return ret;
2934 }
2935 
2936 static int member_cmp_fn(void *obj1, void *obj2, int flags)
2937 {
2938  struct member *mem1 = obj1;
2939  struct member *mem2 = obj2;
2940  const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
2941 
2942  return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
2943 }
2944 
2945 /*!
2946  * \brief Initialize Queue default values.
2947  * \note the queue's lock must be held before executing this function
2948 */
2949 static void init_queue(struct call_queue *q)
2950 {
2951  int i;
2952  struct penalty_rule *pr_iter;
2953 
2954  q->dead = 0;
2955  q->retry = DEFAULT_RETRY;
2956  q->timeout = DEFAULT_TIMEOUT;
2957  q->maxlen = 0;
2958 
2959  ast_string_field_set(q, context, "");
2960 
2961  q->announcefrequency = 0;
2963  q->announceholdtime = 1;
2964  q->announceposition_only_up = 0;
2965  q->announcepositionlimit = 10; /* Default 10 positions */
2966  q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
2967  q->roundingseconds = 0; /* Default - don't announce seconds */
2968  q->servicelevel = 0;
2969  q->ringinuse = 1;
2970  q->announce_to_first_user = 0;
2971  q->setinterfacevar = 0;
2972  q->setqueuevar = 0;
2973  q->setqueueentryvar = 0;
2975  q->montype = montype_default;
2976  q->monfmt[0] = '\0';
2977  q->reportholdtime = 0;
2978  q->wrapuptime = 0;
2979  q->penaltymemberslimit = 0;
2980  q->joinempty = 0;
2981  q->leavewhenempty = 0;
2982  q->memberdelay = 0;
2983  q->weight = 0;
2984  q->timeoutrestart = 0;
2986  q->randomperiodicannounce = 0;
2987  q->numperiodicannounce = 0;
2990  q->autopausedelay = 0;
2991  if (!q->members) {
2993  /* linear strategy depends on order, so we have to place all members in a list */
2995  } else {
2998  }
2999  }
3000  q->found = 1;
3001 
3002  ast_string_field_set(q, moh, "");
3003  ast_string_field_set(q, sound_next, "queue-youarenext");
3004  ast_string_field_set(q, sound_thereare, "queue-thereare");
3005  ast_string_field_set(q, sound_calls, "queue-callswaiting");
3006  ast_string_field_set(q, queue_quantity1, "queue-quantity1");
3007  ast_string_field_set(q, queue_quantity2, "queue-quantity2");
3008  ast_string_field_set(q, sound_holdtime, "queue-holdtime");
3009  ast_string_field_set(q, sound_minutes, "queue-minutes");
3010  ast_string_field_set(q, sound_minute, "queue-minute");
3011  ast_string_field_set(q, sound_seconds, "queue-seconds");
3012  ast_string_field_set(q, sound_thanks, "queue-thankyou");
3013  ast_string_field_set(q, sound_reporthold, "queue-reporthold");
3014 
3015  if (!q->sound_periodicannounce[0]) {
3017  }
3018 
3019  if (q->sound_periodicannounce[0]) {
3020  ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
3021  }
3022 
3023  for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3024  if (q->sound_periodicannounce[i]) {
3025  ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
3026  }
3027  }
3028 
3029  while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
3030  ast_free(pr_iter);
3031  }
3032 
3033  /* On restart assume no members are available.
3034  * The queue_avail hint is a boolean state to indicate whether a member is available or not.
3035  *
3036  * This seems counter intuitive, but is required to light a BLF
3037  * AST_DEVICE_INUSE indicates no members are available.
3038  * AST_DEVICE_NOT_INUSE indicates a member is available.
3039  */
3041 }
3042 
3043 static void clear_queue(struct call_queue *q)
3044 {
3045  q->holdtime = 0;
3046  q->callscompleted = 0;
3047  q->callsabandoned = 0;
3048  q->callscompletedinsl = 0;
3049  q->callsabandonedinsl = 0;
3050  q->talktime = 0;
3051 
3052  if (q->members) {
3053  struct member *mem;
3054  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3055  while ((mem = ao2_iterator_next(&mem_iter))) {
3056  mem->calls = 0;
3057  mem->callcompletedinsl = 0;
3058  mem->lastcall = 0;
3059  mem->starttime = 0;
3060  ao2_ref(mem, -1);
3061  }
3062  ao2_iterator_destroy(&mem_iter);
3063  }
3064 }
3065 
3066 /*!
3067  * \brief Change queue penalty by adding rule.
3068  *
3069  * Check rule for errors with time or formatting, see if rule is relative to rest
3070  * of queue, iterate list of rules to find correct insertion point, insert and return.
3071  * \retval -1 on failure
3072  * \retval 0 on success
3073  * \note Call this with the rule_lists locked
3074 */
3075 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
3076 {
3077  char *timestr, *maxstr, *minstr, *raisestr, *contentdup;
3078  struct penalty_rule *rule = NULL, *rule_iter;
3079  struct rule_list *rl_iter;
3080  int penaltychangetime, inserted = 0;
3081 
3082  if (!(rule = ast_calloc(1, sizeof(*rule)))) {
3083  return -1;
3084  }
3085 
3086  contentdup = ast_strdupa(content);
3087 
3088  if (!(maxstr = strchr(contentdup, ','))) {
3089  ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
3090  ast_free(rule);
3091  return -1;
3092  }
3093 
3094  *maxstr++ = '\0';
3095  if ((minstr = strchr(maxstr,','))) {
3096  *minstr++ = '\0';
3097  if ((raisestr = strchr(minstr,','))) {
3098  *raisestr++ = '\0';
3099  }
3100  } else {
3101  raisestr = NULL;
3102  }
3103 
3104  timestr = contentdup;
3105  if ((penaltychangetime = atoi(timestr)) < 0) {
3106  ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
3107  ast_free(rule);
3108  return -1;
3109  }
3110 
3111  rule->time = penaltychangetime;
3112 
3113  /* The last check will evaluate true if either no penalty change is indicated for a given rule
3114  * OR if a min penalty change is indicated but no max penalty change is */
3115  if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
3116  rule->max_relative = 1;
3117  }
3118 
3119  rule->max_value = atoi(maxstr);
3120 
3121  if (!ast_strlen_zero(minstr)) {
3122  if (*minstr == '+' || *minstr == '-') {
3123  rule->min_relative = 1;
3124  }
3125  rule->min_value = atoi(minstr);
3126  } else { /*there was no minimum specified, so assume this means no change*/
3127  rule->min_relative = 1;
3128  }
3129 
3130  if (!ast_strlen_zero(raisestr)) {
3131  if (*raisestr == '+' || *raisestr == '-') {
3132  rule->raise_relative = 1;
3133  }
3134  rule->raise_value = atoi(raisestr);
3135  } else { /*there was no raise specified, so assume this means no change*/
3136  rule->raise_relative = 1;
3137  }
3138 
3139  /*We have the rule made, now we need to insert it where it belongs*/
3140  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
3141  if (strcasecmp(rl_iter->name, list_name)) {
3142  continue;
3143  }
3144 
3145  AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
3146  if (rule->time < rule_iter->time) {
3148  inserted = 1;
3149  break;
3150  }
3151  }
3153 
3154  if (!inserted) {
3155  AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
3156  inserted = 1;
3157  }
3158 
3159  break;
3160  }
3161 
3162  if (!inserted) {
3163  ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
3164  ast_free(rule);
3165  return -1;
3166  }
3167  return 0;
3168 }
3169 
3170 /*!
3171  * \brief Load queue rules from realtime.
3172  *
3173  * Check rule for errors with time or formatting, see if rule is relative to rest
3174  * of queue, iterate list of rules to find correct insertion point, insert and return.
3175  * \retval -1 on failure
3176  * \retval 0 on success
3177  * \note Call this with the rule_lists locked
3178 */
3179 static int load_realtime_rules(void)
3180 {
3181  struct ast_config *cfg;
3182  struct rule_list *rl_iter, *new_rl;
3183  struct penalty_rule *pr_iter;
3184  char *rulecat = NULL;
3185 
3186  if (!ast_check_realtime("queue_rules")) {
3187  ast_log(LOG_WARNING, "Missing \"queue_rules\" in extconfig.conf\n");
3188  return 0;
3189  }
3190  if (!(cfg = ast_load_realtime_multientry("queue_rules", "rule_name LIKE", "%", SENTINEL))) {
3191  ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n");
3192  return 0;
3193  }
3194  while ((rulecat = ast_category_browse(cfg, rulecat))) {
3195  const char *timestr, *maxstr, *minstr, *raisestr, *rule_name;
3196  int penaltychangetime, rule_exists = 0, inserted = 0;
3197  int max_penalty = 0, min_penalty = 0, raise_penalty = 0;
3198  int min_relative = 0, max_relative = 0, raise_relative = 0;
3199  struct penalty_rule *new_penalty_rule = NULL;
3200 
3201  rule_name = ast_variable_retrieve(cfg, rulecat, "rule_name");
3202  if (ast_strlen_zero(rule_name)) {
3203  continue;
3204  }
3205 
3206  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
3207  if (!(strcasecmp(rl_iter->name, rule_name))) {
3208  rule_exists = 1;
3209  new_rl = rl_iter;
3210  break;
3211  }
3212  }
3213  if (!rule_exists) {
3214  if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
3215  ast_config_destroy(cfg);
3216  return -1;
3217  }
3218  ast_copy_string(new_rl->name, rule_name, sizeof(new_rl->name));
3220  }
3221  timestr = ast_variable_retrieve(cfg, rulecat, "time");
3222  if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) {
3223  ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules, skipping it\n",
3224  (ast_strlen_zero(timestr) ? "invalid value" : timestr), rule_name);
3225  continue;
3226  }
3227  if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) {
3228  ast_config_destroy(cfg);
3229  return -1;
3230  }
3231  if (!(maxstr = ast_variable_retrieve(cfg, rulecat, "max_penalty")) ||
3232  ast_strlen_zero(maxstr) || sscanf(maxstr, "%30d", &max_penalty) != 1) {
3233  max_penalty = 0;
3234  max_relative = 1;
3235  } else {
3236  if (*maxstr == '+' || *maxstr == '-') {
3237  max_relative = 1;
3238  }
3239  }
3240  if (!(minstr = ast_variable_retrieve(cfg, rulecat, "min_penalty")) ||
3241  ast_strlen_zero(minstr) || sscanf(minstr, "%30d", &min_penalty) != 1) {
3242  min_penalty = 0;
3243  min_relative = 1;
3244  } else {
3245  if (*minstr == '+' || *minstr == '-') {
3246  min_relative = 1;
3247  }
3248  }
3249  if (!(raisestr = ast_variable_retrieve(cfg, rulecat, "raise_penalty")) ||
3250  ast_strlen_zero(raisestr) || sscanf(raisestr, "%30d", &raise_penalty) != 1) {
3251  raise_penalty = 0;
3252  raise_relative = 1;
3253  } else {
3254  if (*raisestr == '+' || *raisestr == '-') {
3255  raise_relative = 1;
3256  }
3257  }
3258  new_penalty_rule->time = penaltychangetime;
3259  new_penalty_rule->max_relative = max_relative;
3260  new_penalty_rule->max_value = max_penalty;
3261  new_penalty_rule->min_relative = min_relative;
3262  new_penalty_rule->min_value = min_penalty;
3263  new_penalty_rule->raise_relative = raise_relative;
3264  new_penalty_rule->raise_value = raise_penalty;
3265  AST_LIST_TRAVERSE_SAFE_BEGIN(&new_rl->rules, pr_iter, list) {
3266  if (new_penalty_rule->time < pr_iter->time) {
3267  AST_LIST_INSERT_BEFORE_CURRENT(new_penalty_rule, list);
3268  inserted = 1;
3269  }
3270  }
3272  if (!inserted) {
3273  AST_LIST_INSERT_TAIL(&new_rl->rules, new_penalty_rule, list);
3274  }
3275  }
3276 
3277  ast_config_destroy(cfg);
3278  return 0;
3279 }
3280 
3281 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
3282 {
3283  char *value_copy = ast_strdupa(value);
3284  char *option = NULL;
3285  while ((option = strsep(&value_copy, ","))) {
3286  if (!strcasecmp(option, "paused")) {
3287  *empty |= QUEUE_EMPTY_PAUSED;
3288  } else if (!strcasecmp(option, "penalty")) {
3289  *empty |= QUEUE_EMPTY_PENALTY;
3290  } else if (!strcasecmp(option, "inuse")) {
3291  *empty |= QUEUE_EMPTY_INUSE;
3292  } else if (!strcasecmp(option, "ringing")) {
3293  *empty |= QUEUE_EMPTY_RINGING;
3294  } else if (!strcasecmp(option, "invalid")) {
3295  *empty |= QUEUE_EMPTY_INVALID;
3296  } else if (!strcasecmp(option, "wrapup")) {
3297  *empty |= QUEUE_EMPTY_WRAPUP;
3298  } else if (!strcasecmp(option, "unavailable")) {
3299  *empty |= QUEUE_EMPTY_UNAVAILABLE;
3300  } else if (!strcasecmp(option, "unknown")) {
3301  *empty |= QUEUE_EMPTY_UNKNOWN;
3302  } else if (!strcasecmp(option, "loose")) {
3304  } else if (!strcasecmp(option, "strict")) {
3306  } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
3308  } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
3309  *empty = 0;
3310  } else {
3311  ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
3312  }
3313  }
3314 }
3315 
3316 /*! \brief Configure a queue parameter.
3317  *
3318  * The failunknown flag is set for config files (and static realtime) to show
3319  * errors for unknown parameters. It is cleared for dynamic realtime to allow
3320  * extra fields in the tables.
3321  * \note For error reporting, line number is passed for .conf static configuration,
3322  * for Realtime queues, linenum is -1.
3323 */
3324 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
3325 {
3326  if (!strcasecmp(param, "musicclass") ||
3327  !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
3328  ast_string_field_set(q, moh, val);
3329  } else if (!strcasecmp(param, "announce")) {
3330  ast_string_field_set(q, announce, val);
3331  } else if (!strcasecmp(param, "context")) {
3333  } else if (!strcasecmp(param, "timeout")) {
3334  q->timeout = atoi(val);
3335  if (q->timeout < 0) {
3336  q->timeout = DEFAULT_TIMEOUT;
3337  }
3338  } else if (!strcasecmp(param, "ringinuse")) {
3339  q->ringinuse = ast_true(val);
3340  } else if (!strcasecmp(param, "setinterfacevar")) {
3342  } else if (!strcasecmp(param, "setqueuevar")) {
3343  q->setqueuevar = ast_true(val);
3344  } else if (!strcasecmp(param, "setqueueentryvar")) {
3346  } else if (!strcasecmp(param, "monitor-format")) {
3347  ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
3348  } else if (!strcasecmp(param, "membermacro")) {
3349  ast_string_field_set(q, membermacro, val);
3350  } else if (!strcasecmp(param, "membergosub")) {
3351  ast_string_field_set(q, membergosub, val);
3352  } else if (!strcasecmp(param, "queue-youarenext")) {
3353  ast_string_field_set(q, sound_next, val);
3354  } else if (!strcasecmp(param, "queue-thereare")) {
3355  ast_string_field_set(q, sound_thereare, val);
3356  } else if (!strcasecmp(param, "queue-callswaiting")) {
3357  ast_string_field_set(q, sound_calls, val);
3358  } else if (!strcasecmp(param, "queue-quantity1")) {
3359  ast_string_field_set(q, queue_quantity1, val);
3360  } else if (!strcasecmp(param, "queue-quantity2")) {
3361  ast_string_field_set(q, queue_quantity2, val);
3362  } else if (!strcasecmp(param, "queue-holdtime")) {
3363  ast_string_field_set(q, sound_holdtime, val);
3364  } else if (!strcasecmp(param, "queue-minutes")) {
3365  ast_string_field_set(q, sound_minutes, val);
3366  } else if (!strcasecmp(param, "queue-minute")) {
3367  ast_string_field_set(q, sound_minute, val);
3368  } else if (!strcasecmp(param, "queue-seconds")) {
3369  ast_string_field_set(q, sound_seconds, val);
3370  } else if (!strcasecmp(param, "queue-thankyou")) {
3371  ast_string_field_set(q, sound_thanks, val);
3372  } else if (!strcasecmp(param, "queue-callerannounce")) {
3373  ast_string_field_set(q, sound_callerannounce, val);
3374  } else if (!strcasecmp(param, "queue-reporthold")) {
3375  ast_string_field_set(q, sound_reporthold, val);
3376  } else if (!strcasecmp(param, "announce-frequency")) {
3377  q->announcefrequency = atoi(val);
3378  } else if (!strcasecmp(param, "announce-to-first-user")) {
3380  } else if (!strcasecmp(param, "min-announce-frequency")) {
3381  q->minannouncefrequency = atoi(val);
3382  ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
3383  } else if (!strcasecmp(param, "announce-round-seconds")) {
3384  q->roundingseconds = atoi(val);
3385  /* Rounding to any other values just doesn't make sense... */
3386  if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
3387  || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
3388  if (linenum >= 0) {
3389  ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
3390  "using 0 instead for queue '%s' at line %d of queues.conf\n",
3391  val, param, q->name, linenum);
3392  } else {
3393  ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
3394  "using 0 instead for queue '%s'\n", val, param, q->name);
3395  }
3396  q->roundingseconds=0;
3397  }
3398  } else if (!strcasecmp(param, "announce-holdtime")) {
3399  if (!strcasecmp(val, "once")) {
3401  } else if (ast_true(val)) {
3403  } else {
3404  q->announceholdtime = 0;
3405  }
3406  } else if (!strcasecmp(param, "announce-position")) {
3407  if (!strcasecmp(val, "limit")) {
3409  } else if (!strcasecmp(val, "more")) {
3411  } else if (ast_true(val)) {
3413  } else {
3415  }
3416  } else if (!strcasecmp(param, "announce-position-only-up")) {
3418  } else if (!strcasecmp(param, "announce-position-limit")) {
3419  q->announcepositionlimit = atoi(val);
3420  } else if (!strcasecmp(param, "periodic-announce")) {
3421  if (strchr(val, ',')) {
3422  char *s, *buf = ast_strdupa(val);
3423  unsigned int i = 0;
3424 
3425  while ((s = strsep(&buf, ",|"))) {
3426  if (!q->sound_periodicannounce[i]) {
3428  }
3429  ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
3430  i++;
3431  if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
3432  break;
3433  }
3434  }
3435  q->numperiodicannounce = i;
3436  } else {
3437  ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
3438  q->numperiodicannounce = 1;
3439  }
3440  } else if (!strcasecmp(param, "periodic-announce-frequency")) {
3441  q->periodicannouncefrequency = atoi(val);
3442  } else if (!strcasecmp(param, "relative-periodic-announce")) {
3444  } else if (!strcasecmp(param, "random-periodic-announce")) {
3446  } else if (!strcasecmp(param, "retry")) {
3447  q->retry = atoi(val);
3448  if (q->retry <= 0) {
3449  q->retry = DEFAULT_RETRY;
3450  }
3451  } else if (!strcasecmp(param, "wrapuptime")) {
3452  q->wrapuptime = atoi(val);
3453  } else if (!strcasecmp(param, "penaltymemberslimit")) {
3454  if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
3455  q->penaltymemberslimit = 0;
3456  }
3457  } else if (!strcasecmp(param, "autofill")) {
3458  q->autofill = ast_true(val);
3459  } else if (!strcasecmp(param, "monitor-type")) {
3460  if (!strcasecmp(val, "mixmonitor")) {
3461  q->montype = 1;
3462  }
3463  } else if (!strcasecmp(param, "autopause")) {
3464  q->autopause = autopause2int(val);
3465  } else if (!strcasecmp(param, "autopausedelay")) {
3466  q->autopausedelay = atoi(val);
3467  } else if (!strcasecmp(param, "autopausebusy")) {
3468  q->autopausebusy = ast_true(val);
3469  } else if (!strcasecmp(param, "autopauseunavail")) {
3471  } else if (!strcasecmp(param, "maxlen")) {
3472  q->maxlen = atoi(val);
3473  if (q->maxlen < 0) {
3474  q->maxlen = 0;
3475  }
3476  } else if (!strcasecmp(param, "servicelevel")) {
3477  q->servicelevel= atoi(val);
3478  } else if (!strcasecmp(param, "strategy")) {
3479  int strategy;
3480 
3481  /* We are a static queue and already have set this, no need to do it again */
3482  if (failunknown) {
3483  return;
3484  }
3485  strategy = strat2int(val);
3486  if (strategy < 0) {
3487  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3488  val, q->name);
3490  }
3491  if (strategy == q->strategy) {
3492  return;
3493  }
3495  ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
3496  return;
3497  }
3498  q->strategy = strategy;
3499  } else if (!strcasecmp(param, "joinempty")) {
3501  } else if (!strcasecmp(param, "leavewhenempty")) {
3503  } else if (!strcasecmp(param, "reportholdtime")) {
3504  q->reportholdtime = ast_true(val);
3505  } else if (!strcasecmp(param, "memberdelay")) {
3506  q->memberdelay = atoi(val);
3507  } else if (!strcasecmp(param, "weight")) {
3508  q->weight = atoi(val);
3509  } else if (!strcasecmp(param, "timeoutrestart")) {
3510  q->timeoutrestart = ast_true(val);
3511  } else if (!strcasecmp(param, "defaultrule")) {
3512  ast_string_field_set(q, defaultrule, val);
3513  } else if (!strcasecmp(param, "timeoutpriority")) {
3514  if (!strcasecmp(val, "conf")) {
3516  } else {
3518  }
3519  } else if (failunknown) {
3520  if (linenum >= 0) {
3521  ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
3522  q->name, param, linenum);
3523  } else {
3524  ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
3525  }
3526  }
3527 }
3528 
3529 
3530 #define QUEUE_PAUSED_DEVSTATE AST_DEVICE_INUSE
3531 #define QUEUE_UNPAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
3532 #define QUEUE_UNKNOWN_PAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
3533 
3534 /*! \internal
3535  * \brief If adding a single new member to a queue, use this function instead of ao2_linking.
3536  * This adds round robin queue position data for a fresh member as well as links it.
3537  * \param queue Which queue the member is being added to
3538  * \param mem Which member is being added to the queue
3539  */
3540 static void member_add_to_queue(struct call_queue *queue, struct member *mem)
3541 {
3542  ao2_lock(queue->members);
3543  mem->queuepos = ao2_container_count(queue->members);
3544  ao2_link(queue->members, mem);
3546  AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
3547  ao2_unlock(queue->members);
3548 }
3549 
3550 /*! \internal
3551  * \brief If removing a single member from a queue, use this function instead of ao2_unlinking.
3552  * This will perform round robin queue position reordering for the remaining members.
3553  * \param queue Which queue the member is being removed from
3554  * \param mem Which member is being removed from the queue
3555  */
3556 static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
3557 {
3559  ao2_lock(queue->members);
3561  queue_member_follower_removal(queue, mem);
3562  ao2_unlink(queue->members, mem);
3563  ao2_unlock(queue->members);
3564 }
3565 
3566 /*!
3567  * \brief Find rt member record to update otherwise create one.
3568  *
3569  * Search for member in queue, if found update penalty/paused state,
3570  * if no member exists create one flag it as a RT member and add to queue member list.
3571 */
3572 static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config)
3573 {
3574  struct member *m;
3575  struct ao2_iterator mem_iter;
3576  int penalty = 0;
3577  int paused = 0;
3578  int found = 0;
3579  int wrapuptime = 0;
3580  int ringinuse = q->ringinuse;
3581 
3582  const char *config_val;
3583  const char *interface = ast_variable_retrieve(member_config, category, "interface");
3584  const char *rt_uniqueid = ast_variable_retrieve(member_config, category, "uniqueid");
3585  const char *membername = S_OR(ast_variable_retrieve(member_config, category, "membername"), interface);
3586  const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface);
3587  const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty");
3588  const char *paused_str = ast_variable_retrieve(member_config, category, "paused");
3589  const char *wrapuptime_str = ast_variable_retrieve(member_config, category, "wrapuptime");
3590 
3591  if (ast_strlen_zero(rt_uniqueid)) {
3592  ast_log(LOG_WARNING, "Realtime field 'uniqueid' is empty for member %s\n",
3593  S_OR(membername, "NULL"));
3594  return;
3595  }
3596 
3597  if (ast_strlen_zero(interface)) {
3598  ast_log(LOG_WARNING, "Realtime field 'interface' is empty for member %s\n",
3599  S_OR(membername, "NULL"));
3600  return;
3601  }
3602 
3603  if (penalty_str) {
3604  penalty = atoi(penalty_str);
3605  if ((penalty < 0) && negative_penalty_invalid) {
3606  return;
3607  } else if (penalty < 0) {
3608  penalty = 0;
3609  }
3610  }
3611 
3612  if (paused_str) {
3613  paused = atoi(paused_str);
3614  if (paused < 0) {
3615  paused = 0;
3616  }
3617  }
3618 
3619  if (wrapuptime_str) {
3620  wrapuptime = atoi(wrapuptime_str);
3621  if (wrapuptime < 0) {
3622  wrapuptime = 0;
3623  }
3624  }
3625 
3626  if ((config_val = ast_variable_retrieve(member_config, category, realtime_ringinuse_field))) {
3627  if (ast_true(config_val)) {
3628  ringinuse = 1;
3629  } else if (ast_false(config_val)) {
3630  ringinuse = 0;
3631  } else {
3632  ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
3633  }
3634  }
3635 
3636  /* Find member by realtime uniqueid and update */
3637  mem_iter = ao2_iterator_init(q->members, 0);
3638  while ((m = ao2_iterator_next(&mem_iter))) {
3639  if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
3640  m->dead = 0; /* Do not delete this one. */
3641  ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
3642  if (paused_str) {
3643  m->paused = paused;
3644  if (paused && m->lastpause == 0) {
3645  time(&m->lastpause); /* XXX: Should this come from realtime? */
3646  }
3648  AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, m->interface);
3649  }
3650  if (strcasecmp(state_interface, m->state_interface)) {
3651  ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
3652  }
3653  m->penalty = penalty;
3654  m->ringinuse = ringinuse;
3655  m->wrapuptime = wrapuptime;
3656  found = 1;
3657  ao2_ref(m, -1);
3658  break;
3659  }
3660  ao2_ref(m, -1);
3661  }
3662  ao2_iterator_destroy(&mem_iter);
3663 
3664  /* Create a new member */
3665  if (!found) {
3666  if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse, wrapuptime))) {
3667  m->dead = 0;
3668  m->realtime = 1;
3669  ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
3670  if (!log_membername_as_agent) {
3671  ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
3672  } else {
3673  ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
3674  }
3675  member_add_to_queue(q, m);
3676  ao2_ref(m, -1);
3677  m = NULL;
3678  }
3679  }
3680 }
3681 
3682 /*! \brief Iterate through queue's member list and delete them */
3683 static void free_members(struct call_queue *q, int all)
3684 {
3685  /* Free non-dynamic members */
3686  struct member *cur;
3687  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3688 
3689  while ((cur = ao2_iterator_next(&mem_iter))) {
3690  if (all || !cur->dynamic) {
3691  member_remove_from_queue(q, cur);
3692  }
3693  ao2_ref(cur, -1);
3694  }
3695  ao2_iterator_destroy(&mem_iter);
3696 }
3697 
3698 /*! \brief Free queue's member list then its string fields */
3699 static void destroy_queue(void *obj)
3700 {
3701  struct call_queue *q = obj;
3702  int i;
3703 
3704  free_members(q, 1);
3706  for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3707  if (q->sound_periodicannounce[i]) {
3709  }
3710  }
3711  ao2_ref(q->members, -1);
3712 }
3713 
3714 static struct call_queue *alloc_queue(const char *queuename)
3715 {
3716  struct call_queue *q;
3717 
3718  if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
3719  if (ast_string_field_init(q, 64)) {
3720  queue_t_unref(q, "String field allocation failed");
3721  return NULL;
3722  }
3723  ast_string_field_set(q, name, queuename);
3724  }
3725  return q;
3726 }
3727 
3728 /*!
3729  * \brief Reload a single queue via realtime.
3730  *
3731  * Check for statically defined queue first, check if deleted RT queue,
3732  * check for new RT queue, if queue vars are not defined init them with defaults.
3733  * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
3734  * \retval the queue,
3735  * \retval NULL if it doesn't exist.
3736  * \note Should be called with the "queues" container locked.
3737 */
3738 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
3739 {
3740  struct ast_variable *v;
3741  struct call_queue *q, tmpq = {
3742  .name = queuename,
3743  };
3744  struct member *m;
3745  struct ao2_iterator mem_iter;
3746  char *category = NULL;
3747  const char *tmp_name;
3748  char *tmp;
3749  char tmpbuf[64]; /* Must be longer than the longest queue param name. */
3750 
3751  /* Static queues override realtime. */
3752  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
3753  ao2_lock(q);
3754  if (!q->realtime) {
3755  if (q->dead) {
3756  ao2_unlock(q);
3757  queue_t_unref(q, "Queue is dead; can't return it");
3758  return NULL;
3759  }
3760  ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
3761  ao2_unlock(q);
3762  return q;
3763  }
3764  } else if (!member_config) {
3765  /* Not found in the list, and it's not realtime ... */
3766  return NULL;
3767  }
3768  /* Check if queue is defined in realtime. */
3769  if (!queue_vars) {
3770  /* Delete queue from in-core list if it has been deleted in realtime. */
3771  if (q) {
3772  /*! \note Hmm, can't seem to distinguish a DB failure from a not
3773  found condition... So we might delete an in-core queue
3774  in case of DB failure. */
3775  ast_debug(1, "Queue %s not found in realtime.\n", queuename);
3776 
3777  q->dead = 1;
3778  /* Delete if unused (else will be deleted when last caller leaves). */
3779  queues_t_unlink(queues, q, "Unused; removing from container");
3780  ao2_unlock(q);
3781  queue_t_unref(q, "Queue is dead; can't return it");
3782  }
3783  return NULL;
3784  }
3785 
3786  /* Create a new queue if an in-core entry does not exist yet. */
3787  if (!q) {
3788  struct ast_variable *tmpvar = NULL;
3789  if (!(q = alloc_queue(queuename))) {
3790  return NULL;
3791  }
3792  ao2_lock(q);
3793  clear_queue(q);
3794  q->realtime = 1;
3795  /*Before we initialize the queue, we need to set the strategy, so that linear strategy
3796  * will allocate the members properly
3797  */
3798  for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
3799  if (!strcasecmp(tmpvar->name, "strategy")) {
3800  q->strategy = strat2int(tmpvar->value);
3801  if (q->strategy < 0) {
3802  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3803  tmpvar->value, q->name);
3805  }
3806  break;
3807  }
3808  }
3809  /* We traversed all variables and didn't find a strategy */
3810  if (!tmpvar) {
3812  }
3813  queues_t_link(queues, q, "Add queue to container");
3814  }
3815  init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
3816 
3817  memset(tmpbuf, 0, sizeof(tmpbuf));
3818  for (v = queue_vars; v; v = v->next) {
3819  /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
3820  if (strchr(v->name, '_')) {
3821  ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
3822  tmp_name = tmpbuf;
3823  tmp = tmpbuf;
3824  while ((tmp = strchr(tmp, '_'))) {
3825  *tmp++ = '-';
3826  }
3827  } else {
3828  tmp_name = v->name;
3829  }
3830 
3831  /* NULL values don't get returned from realtime; blank values should
3832  * still get set. If someone doesn't want a value to be set, they
3833  * should set the realtime column to NULL, not blank. */
3834  queue_set_param(q, tmp_name, v->value, -1, 0);
3835  }
3836 
3837  /* Temporarily set realtime members dead so we can detect deleted ones. */
3838  mem_iter = ao2_iterator_init(q->members, 0);
3839  while ((m = ao2_iterator_next(&mem_iter))) {
3840  if (m->realtime) {
3841  m->dead = 1;
3842  }
3843  ao2_ref(m, -1);
3844  }
3845  ao2_iterator_destroy(&mem_iter);
3846 
3847  while ((category = ast_category_browse(member_config, category))) {
3848  rt_handle_member_record(q, category, member_config);
3849  }
3850 
3851  /* Delete all realtime members that have been deleted in DB. */
3852  mem_iter = ao2_iterator_init(q->members, 0);
3853  while ((m = ao2_iterator_next(&mem_iter))) {
3854  if (m->dead) {
3856  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
3857  } else {
3858  ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
3859  }
3861  }
3862  ao2_ref(m, -1);
3863  }
3864  ao2_iterator_destroy(&mem_iter);
3865 
3866  ao2_unlock(q);
3867 
3868  return q;
3869 }
3870 
3871 /*!
3872  * note */
3873 
3874 /*!
3875  * \internal
3876  * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
3877  * \param queuename - name of the desired queue
3878  *
3879  * \retval the queue
3880  * \retval NULL if it doesn't exist
3881  */
3882 static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
3883 {
3884  struct ast_variable *queue_vars;
3885  struct ast_config *member_config = NULL;
3886  struct call_queue *q = NULL, tmpq = {
3887  .name = queuename,
3888  };
3889  int prev_weight = 0;
3890 
3891  /* Find the queue in the in-core list first. */
3892  q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
3893 
3894  if (!q || q->realtime) {
3895  /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
3896  queue operations while waiting for the DB.
3897 
3898  This will be two separate database transactions, so we might
3899  see queue parameters as they were before another process
3900  changed the queue and member list as it was after the change.
3901  Thus we might see an empty member list when a queue is
3902  deleted. In practise, this is unlikely to cause a problem. */
3903 
3904  queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
3905  if (queue_vars) {
3906  member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
3907  if (!member_config) {
3908  ast_debug(1, "No queue_members defined in config extconfig.conf\n");
3909  member_config = ast_config_new();
3910  }
3911  }
3912  if (q) {
3913  prev_weight = q->weight ? 1 : 0;
3914  queue_t_unref(q, "Need to find realtime queue");
3915  }
3916 
3917  q = find_queue_by_name_rt(queuename, queue_vars, member_config);
3918  ast_config_destroy(member_config);
3919  ast_variables_destroy(queue_vars);
3920 
3921  /* update the use_weight value if the queue's has gained or lost a weight */
3922  if (q) {
3923  if (!q->weight && prev_weight) {
3925  }
3926  if (q->weight && !prev_weight) {
3928  }
3929  }
3930  /* Other cases will end up with the proper value for use_weight */
3931  } else {
3933  }
3934  return q;
3935 }
3936 
3937 /*!
3938  * \internal
3939  * \brief Load queues and members from realtime.
3940  *
3941  * \param queuename - name of the desired queue to load or empty if need to load all queues
3942 */
3943 static void load_realtime_queues(const char *queuename)
3944 {
3945  struct ast_config *cfg = NULL;
3946  char *category = NULL;
3947  const char *name = NULL;
3948  struct call_queue *q = NULL;
3949 
3950  if (!ast_check_realtime("queues")) {
3951  return;
3952  }
3953 
3954  if (ast_strlen_zero(queuename)) {
3955  if ((cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL))) {
3956  while ((category = ast_category_browse(cfg, category))) {
3957  name = ast_variable_retrieve(cfg, category, "name");
3959  queue_unref(q);
3960  }
3961  }
3962  ast_config_destroy(cfg);
3963  }
3964  } else {
3965  if ((q = find_load_queue_rt_friendly(queuename))) {
3966  queue_unref(q);
3967  }
3968  }
3969 }
3970 
3971 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
3972 {
3973  int ret = -1;
3974 
3975  if (ast_strlen_zero(mem->rt_uniqueid)) {
3976  return ret;
3977  }
3978 
3979  if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) >= 0) {
3980  ret = 0;
3981  }
3982 
3983  return ret;
3984 }
3985 
3986 
3987 static void update_realtime_members(struct call_queue *q)
3988 {
3989  struct ast_config *member_config = NULL;
3990  struct member *m;
3991  char *category = NULL;
3992  struct ao2_iterator mem_iter;
3993 
3994  if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
3995  /* This queue doesn't have realtime members. If the queue still has any realtime
3996  * members in memory, they need to be removed.
3997  */
3998  ao2_lock(q);
3999  mem_iter = ao2_iterator_init(q->members, 0);
4000  while ((m = ao2_iterator_next(&mem_iter))) {
4001  if (m->realtime) {
4003  }
4004  ao2_ref(m, -1);
4005  }
4006  ao2_iterator_destroy(&mem_iter);
4007  ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
4008  ao2_unlock(q);
4009  return;
4010  }
4011 
4012  ao2_lock(q);
4013 
4014  /* Temporarily set realtime members dead so we can detect deleted ones.*/
4015  mem_iter = ao2_iterator_init(q->members, 0);
4016  while ((m = ao2_iterator_next(&mem_iter))) {
4017  if (m->realtime) {
4018  m->dead = 1;
4019  }
4020  ao2_ref(m, -1);
4021  }
4022  ao2_iterator_destroy(&mem_iter);
4023 
4024  while ((category = ast_category_browse(member_config, category))) {
4025  rt_handle_member_record(q, category, member_config);
4026  }
4027 
4028  /* Delete all realtime members that have been deleted in DB. */
4029  mem_iter = ao2_iterator_init(q->members, 0);
4030  while ((m = ao2_iterator_next(&mem_iter))) {
4031  if (m->dead) {
4033  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
4034  } else {
4035  ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
4036  }
4038  }
4039  ao2_ref(m, -1);
4040  }
4041  ao2_iterator_destroy(&mem_iter);
4042  ao2_unlock(q);
4043  ast_config_destroy(member_config);
4044 }
4045 
4046 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
4047 {
4048  struct call_queue *q;
4049  struct queue_ent *cur, *prev = NULL;
4050  int res = -1;
4051  int pos = 0;
4052  int inserted = 0;
4053 
4054  if (!(q = find_load_queue_rt_friendly(queuename))) {
4055  return res;
4056  }
4057  ao2_lock(q);
4058 
4059  /* This is our one */
4060  if (q->joinempty) {
4061  int status = 0;
4062  if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, qe->raise_penalty, q->joinempty, 0))) {
4063  *reason = QUEUE_JOINEMPTY;
4064  ao2_unlock(q);
4065  queue_t_unref(q, "Done with realtime queue");
4066  return res;
4067  }
4068  }
4069  if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
4070  *reason = QUEUE_FULL;
4071  } else if (*reason == QUEUE_UNKNOWN) {
4072  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4073 
4074  /* There's space for us, put us at the right position inside
4075  * the queue.
4076  * Take into account the priority of the calling user */
4077  inserted = 0;
4078  prev = NULL;
4079  cur = q->head;
4080  while (cur) {
4081  /* We have higher priority than the current user, enter
4082  * before him, after all the other users with priority
4083  * higher or equal to our priority. */
4084  if ((!inserted) && (qe->prio > cur->prio)) {
4085  insert_entry(q, prev, qe, &pos);
4086  inserted = 1;
4087  }
4088  /* <= is necessary for the position comparison because it may not be possible to enter
4089  * at our desired position since higher-priority callers may have taken the position we want
4090  */
4091  if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
4092  insert_entry(q, prev, qe, &pos);
4093  inserted = 1;
4094  /*pos is incremented inside insert_entry, so don't need to add 1 here*/
4095  if (position < pos) {
4096  ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
4097  }
4098  }
4099  cur->pos = ++pos;
4100  prev = cur;
4101  cur = cur->next;
4102  }
4103  /* No luck, join at the end of the queue */
4104  if (!inserted) {
4105  insert_entry(q, prev, qe, &pos);
4106  }
4107  ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
4108  ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
4109  ast_copy_string(qe->context, q->context, sizeof(qe->context));
4110  q->count++;
4111  if (q->count == 1) {
4113  }
4114 
4115  res = 0;
4116 
4117  blob = ast_json_pack("{s: s, s: i, s: i}",
4118  "Queue", q->name,
4119  "Position", qe->pos,
4120  "Count", q->count);
4121  ast_channel_publish_cached_blob(qe->chan, queue_caller_join_type(), blob);
4122  ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
4123  }
4124  ao2_unlock(q);
4125  queue_t_unref(q, "Done with realtime queue");
4126 
4127  return res;
4128 }
4129 
4130 static int play_file(struct ast_channel *chan, const char *filename)
4131 {
4132  int res;
4133 
4134  if (ast_strlen_zero(filename)) {
4135  return 0;
4136  }
4137 
4138  if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
4139  return 0;
4140  }
4141 
4143 
4144  res = ast_streamfile(chan, filename, ast_channel_language(chan));
4145  if (!res) {
4147  }
4148 
4150 
4151  return res;
4152 }
4153 
4154 /*!
4155  * \brief Check for valid exit from queue via goto
4156  * \retval 0 if failure
4157  * \retval 1 if successful
4158 */
4159 static int valid_exit(struct queue_ent *qe, char digit)
4160 {
4161  int digitlen = strlen(qe->digits);
4162 
4163  /* Prevent possible buffer overflow */
4164  if (digitlen < sizeof(qe->digits) - 2) {
4165  qe->digits[digitlen] = digit;
4166  qe->digits[digitlen + 1] = '\0';
4167  } else {
4168  qe->digits[0] = '\0';
4169  return 0;
4170  }
4171 
4172  /* If there's no context to goto, short-circuit */
4173  if (ast_strlen_zero(qe->context)) {
4174  return 0;
4175  }
4176 
4177  /* If the extension is bad, then reset the digits to blank */
4178  if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
4180  qe->digits[0] = '\0';
4181  return 0;
4182  }
4183 
4184  /* We have an exact match */
4185  if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
4186  qe->valid_digits = 1;
4187  /* Return 1 on a successful goto */
4188  return 1;
4189  }
4190 
4191  return 0;
4192 }
4193 
4194 static int say_position(struct queue_ent *qe, int ringing)
4195 {
4196  int res = 0, say_thanks = 0;
4197  long avgholdmins, avgholdsecs;
4198  time_t now;
4199 
4200  /* Let minannouncefrequency seconds pass between the start of each position announcement */
4201  time(&now);
4202  if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
4203  return 0;
4204  }
4205 
4206  /* If either our position has changed, or we are over the freq timer, say position */
4207  if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
4208  return 0;
4209  }
4210 
4211  /* Only announce if the caller's queue position has improved since last time */
4212  if (qe->parent->announceposition_only_up && qe->last_pos_said <= qe->pos) {
4213  return 0;
4214  }
4215 
4216  if (ringing) {
4217  ast_indicate(qe->chan,-1);
4218  } else {
4219  ast_moh_stop(qe->chan);
4220  }
4221 
4225  qe->pos <= qe->parent->announcepositionlimit)) {
4226  say_thanks = 1;
4227  /* Say we're next, if we are */
4228  if (qe->pos == 1) {
4229  res = play_file(qe->chan, qe->parent->sound_next);
4230  if (!res) {
4231  goto posout;
4232  }
4233  /* Say there are more than N callers */
4235  res = (
4236  play_file(qe->chan, qe->parent->queue_quantity1) ||
4238  ast_channel_language(qe->chan), NULL) || /* Needs gender */
4239  play_file(qe->chan, qe->parent->queue_quantity2));
4240  /* Say there are currently N callers waiting */
4241  } else {
4242  res = (
4243  play_file(qe->chan, qe->parent->sound_thereare) ||
4245  ast_channel_language(qe->chan), "n") || /* Needs gender */
4246  play_file(qe->chan, qe->parent->sound_calls));
4247  }
4248  if (res) {
4249  goto playout;
4250  }
4251  }
4252  /* Round hold time to nearest minute */
4253  avgholdmins = labs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
4254 
4255  /* If they have specified a rounding then round the seconds as well */
4256  if (qe->parent->roundingseconds) {
4257  avgholdsecs = (labs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
4258  avgholdsecs *= qe->parent->roundingseconds;
4259  } else {
4260  avgholdsecs = 0;
4261  }
4262 
4263  ast_verb(3, "Hold time for %s is %ld minute(s) %ld seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
4264 
4265  /* If the hold time is >1 min, if it's enabled, and if it's not
4266  supposed to be only once and we have already said it, say it */
4267  if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
4270  say_thanks = 1;
4271  res = play_file(qe->chan, qe->parent->sound_holdtime);
4272  if (res) {
4273  goto playout;
4274  }
4275 
4276  if (avgholdmins >= 1) {
4277  res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), "n");
4278  if (res) {
4279  goto playout;
4280  }
4281 
4282  if (avgholdmins == 1) {
4283  res = play_file(qe->chan, qe->parent->sound_minute);
4284  if (res) {
4285  goto playout;
4286  }
4287  } else {
4288  res = play_file(qe->chan, qe->parent->sound_minutes);
4289  if (res) {
4290  goto playout;
4291  }
4292  }
4293  }
4294  if (avgholdsecs >= 1) {
4295  res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), "n");
4296  if (res) {
4297  goto playout;
4298  }
4299 
4300  res = play_file(qe->chan, qe->parent->sound_seconds);
4301  if (res) {
4302  goto playout;
4303  }
4304  }
4305  }
4306 
4307 posout:
4308  if (qe->parent->announceposition) {
4309  ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
4310  ast_channel_name(qe->chan), qe->parent->name, qe->pos);
4311  }
4312  if (say_thanks) {
4313  res = play_file(qe->chan, qe->parent->sound_thanks);
4314  }
4315 playout:
4316 
4317  if ((res > 0 && !valid_exit(qe, res))) {
4318  res = 0;
4319  }
4320 
4321  /* Set our last_pos indicators */
4322  qe->last_pos = now;
4323  qe->last_pos_said = qe->pos;
4324 
4325  /* Don't restart music on hold if we're about to exit the caller from the queue */
4326  if (!res) {
4327  if (ringing) {
4329  } else {
4330  ast_moh_start(qe->chan, qe->moh, NULL);
4331  }
4332  }
4333  return res;
4334 }
4335 
4336 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
4337 {
4338  int oldvalue;
4339 
4340  /* Calculate holdtime using an exponential average */
4341  /* Thanks to SRT for this contribution */
4342  /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
4343 
4344  ao2_lock(qe->parent);
4345  if ((qe->parent->callscompleted + qe->parent->callsabandoned) == 0) {
4346  qe->parent->holdtime = newholdtime;
4347  } else {
4348  oldvalue = qe->parent->holdtime;
4349  qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
4350  }
4351  ao2_unlock(qe->parent);
4352 }
4353 
4354 /*! \brief Caller leaving queue.
4355  *
4356  * Search the queue to find the leaving client, if found remove from queue
4357  * create manager event, move others up the queue.
4358 */
4359 static void leave_queue(struct queue_ent *qe)
4360 {
4361  struct call_queue *q;
4362  struct queue_ent *current, *prev = NULL;
4363  struct penalty_rule *pr_iter;
4364  int pos = 0;
4365 
4366  if (!(q = qe->parent)) {
4367  return;
4368  }
4369  queue_t_ref(q, "Copy queue pointer from queue entry");
4370  ao2_lock(q);
4371 
4372  prev = NULL;
4373  for (current = q->head; current; current = current->next) {
4374  if (current == qe) {
4375  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4376  char posstr[20];
4377  q->count--;
4378  if (!q->count) {
4380  }
4381 
4382  blob = ast_json_pack("{s: s, s: i, s: i}",
4383  "Queue", q->name,
4384  "Position", qe->pos,
4385  "Count", q->count);
4386  ast_channel_publish_cached_blob(qe->chan, queue_caller_leave_type(), blob);
4387  ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
4388  /* Take us out of the queue */
4389  if (prev) {
4390  prev->next = current->next;
4391  } else {
4392  q->head = current->next;
4393  }
4394  /* Free penalty rules */
4395  while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
4396  ast_free(pr_iter);
4397  }
4398  qe->pr = NULL;
4399  snprintf(posstr, sizeof(posstr), "%d", qe->pos);
4400  pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
4401  } else {
4402  /* Renumber the people after us in the queue based on a new count */
4403  current->pos = ++pos;
4404  prev = current;
4405  }
4406  }
4407  ao2_unlock(q);
4408 
4409  /*If the queue is a realtime queue, check to see if it's still defined in real time*/
4410  if (q->realtime) {
4411  struct ast_variable *var;
4412  if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
4413  q->dead = 1;
4414  } else {
4416  }
4417  }
4418 
4419  if (q->dead) {
4420  /* It's dead and nobody is in it, so kill it */
4421  queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
4422  }
4423  /* unref the explicit ref earlier in the function */
4424  queue_t_unref(q, "Expire copied reference");
4425 }
4426 
4427 /*!
4428  * \internal
4429  * \brief Destroy the given callattempt structure and free it.
4430  * \since 1.8
4431  *
4432  * \param doomed callattempt structure to destroy.
4433  */
4434 static void callattempt_free(struct callattempt *doomed)
4435 {
4436  if (doomed->member) {
4437  ao2_ref(doomed->member, -1);
4438  }
4440  ast_free(doomed->orig_chan_name);
4441  ast_free(doomed);
4442 }
4443 
4444 static void publish_dial_end_event(struct ast_channel *in, struct callattempt *outgoing, struct ast_channel *exception, const char *status)
4445 {
4446  struct callattempt *cur;
4447 
4448  for (cur = outgoing; cur; cur = cur->q_next) {
4449  if (cur->chan && cur->chan != exception) {
4451  }
4452  }
4453 }
4454 
4455 /*! \brief Hang up a list of outgoing calls */
4456 static void hangupcalls(struct queue_ent *qe, struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
4457 {
4458  struct callattempt *oo;
4459 
4460  while (outgoing) {
4461  /* If someone else answered the call we should indicate this in the CANCEL */
4462  /* Hangup any existing lines we have open */
4463  if (outgoing->chan && (outgoing->chan != exception)) {
4464  if (exception || cancel_answered_elsewhere) {
4466  }
4467  ast_channel_publish_dial(qe->chan, outgoing->chan, outgoing->interface, "CANCEL");
4468 
4469  /* When dialing channels it is possible that they may not ever
4470  * leave the not in use state (Local channels in particular) by
4471  * the time we cancel them. If this occurs but we know they were
4472  * dialed we explicitly remove them from the pending members
4473  * container so that subsequent call attempts occur.
4474  */
4475  if (outgoing->member->status == AST_DEVICE_NOT_INUSE) {
4477  }
4478 
4479  ast_hangup(outgoing->chan);
4480  }
4481  oo = outgoing;
4482  outgoing = outgoing->q_next;
4484  callattempt_free(oo);
4485  }
4486 }
4487 
4488 /*!
4489  * \brief Get the number of members available to accept a call.
4490  *
4491  * \note The queue passed in should be locked prior to this function call
4492  *
4493  * \param[in] q The queue for which we are counting the number of available members
4494  * \return Return the number of available members in queue q
4495  */
4496 static int num_available_members(struct call_queue *q)
4497 {
4498  struct member *mem;
4499  int avl = 0;
4500  struct ao2_iterator mem_iter;
4501 
4502  mem_iter = ao2_iterator_init(q->members, 0);
4503  while ((mem = ao2_iterator_next(&mem_iter))) {
4504 
4505  avl += is_member_available(q, mem);
4506  ao2_ref(mem, -1);
4507 
4508  /* If autofill is not enabled or if the queue's strategy is ringall, then
4509  * we really don't care about the number of available members so much as we
4510  * do that there is at least one available.
4511  *
4512  * In fact, we purposely will return from this function stating that only
4513  * one member is available if either of those conditions hold. That way,
4514  * functions which determine what action to take based on the number of available
4515  * members will operate properly. The reasoning is that even if multiple
4516  * members are available, only the head caller can actually be serviced.
4517  */
4518  if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
4519  break;
4520  }
4521  }
4522  ao2_iterator_destroy(&mem_iter);
4523 
4524  return avl;
4525 }
4526 
4527 /* traverse all defined queues which have calls waiting and contain this member
4528  return 0 if no other queue has precedence (higher weight) or 1 if found */
4529 static int compare_weight(struct call_queue *rq, struct member *member)
4530 {
4531  struct call_queue *q;
4532  struct member *mem;
4533  int found = 0;
4534  struct ao2_iterator queue_iter;
4535 
4536  queue_iter = ao2_iterator_init(queues, 0);
4537  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4538  if (q == rq) { /* don't check myself, could deadlock */
4539  queue_t_unref(q, "Done with iterator");
4540  continue;
4541  }
4542  ao2_lock(q);
4543  if (q->count && q->members) {
4544  if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
4545  ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
4546  if (q->weight > rq->weight && q->count >= num_available_members(q)) {
4547  ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
4548  found = 1;
4549  }
4550  ao2_ref(mem, -1);
4551  }
4552  }
4553  ao2_unlock(q);
4554  queue_t_unref(q, "Done with iterator");
4555  if (found) {
4556  break;
4557  }
4558  }
4559  ao2_iterator_destroy(&queue_iter);
4560  return found;
4561 }
4562 
4563 /*! \brief common hangup actions */
4564 static void do_hang(struct callattempt *o)
4565 {
4566  o->stillgoing = 0;
4567  ast_hangup(o->chan);
4569  o->chan = NULL;
4570 }
4571 
4572 /*!
4573  * \internal
4574  * \brief Check if the member status is available.
4575  *
4576  * \param status Member status to check if available.
4577  *
4578  * \retval non-zero if the member status is available.
4579  */
4581 {
4583 }
4584 
4585 /*!
4586  * \internal
4587  * \brief Determine if can ring a queue entry.
4588  *
4589  * \param qe Queue entry to check.
4590  * \param call Member call attempt.
4591  *
4592  * \retval non-zero if an entry can be called.
4593  */
4594 static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
4595 {
4596  struct member *memberp = call->member;
4597  int wrapuptime;
4598 
4599  if (memberp->paused) {
4600  ast_debug(1, "%s paused, can't receive call\n", call->interface);
4601  return 0;
4602  }
4603 
4604  if (!memberp->ringinuse && !member_status_available(memberp->status)) {
4605  ast_debug(1, "%s not available, can't receive call\n", call->interface);
4606  return 0;
4607  }
4608 
4609  if (memberp->lastqueue) {
4610  wrapuptime = get_wrapuptime(memberp->lastqueue, memberp);
4611  } else {
4612  wrapuptime = get_wrapuptime(qe->parent, memberp);
4613  }
4614  if (wrapuptime && (time(NULL) - memberp->lastcall) < wrapuptime) {
4615  ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
4616  (memberp->lastqueue ? memberp->lastqueue->name : qe->parent->name),
4617  call->interface);
4618  return 0;
4619  }
4620 
4621  if (use_weight && compare_weight(qe->parent, memberp)) {
4622  ast_debug(1, "Priority queue delaying call to %s:%s\n",
4623  qe->parent->name, call->interface);
4624  return 0;
4625  }
4626 
4627  if (!memberp->ringinuse) {
4628  struct member *mem;
4629 
4631 
4632  mem = ao2_find(pending_members, memberp,
4634  if (mem) {
4635  /*
4636  * If found that means this member is currently being attempted
4637  * from another calling thread, so stop trying from this thread
4638  */
4639  ast_debug(1, "%s has another call trying, can't receive call\n",
4640  call->interface);
4641  ao2_ref(mem, -1);
4643  return 0;
4644  }
4645 
4646  /*
4647  * If not found add it to the container so another queue
4648  * won't attempt to call this member at the same time.
4649  */
4650  ast_debug(3, "Add %s to pending_members\n", memberp->membername);
4651  ao2_link(pending_members, memberp);
4653 
4654  /*
4655  * The queue member is available. Get current status to be sure
4656  * because the device state and extension state callbacks may
4657  * not have updated the status yet.
4658  */
4660  ast_debug(1, "%s actually not available, can't receive call\n",
4661  call->interface);
4662  pending_members_remove(memberp);
4663  return 0;
4664  }
4665  }
4666 
4667  return 1;
4668 }
4669 
4670 /*!
4671  * \brief Part 2 of ring_one
4672  *
4673  * Does error checking before attempting to request a channel and call a member.
4674  * This function is only called from ring_one().
4675  * Failure can occur if:
4676  * - Agent on call
4677  * - Agent is paused
4678  * - Wrapup time not expired
4679  * - Priority by another queue
4680  *
4681  * \retval 1 on success to reach a free agent
4682  * \retval 0 on failure to get agent.
4683  */
4684 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
4685 {
4686  int res;
4687  int status;
4688  char tech[256];
4689  char *location;
4690  const char *macrocontext, *macroexten;
4691  struct ast_format_cap *nativeformats;
4692  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4693 
4694  /* on entry here, we know that tmp->chan == NULL */
4695  if (!can_ring_entry(qe, tmp)) {
4696  tmp->stillgoing = 0;
4697  ++*busies;
4698  return 0;
4699  }
4700 
4701  ast_copy_string(tech, tmp->interface, sizeof(tech));
4702  if ((location = strchr(tech, '/'))) {
4703  *location++ = '\0';
4704  } else {
4705  location = "";
4706  }
4707 
4708  ast_channel_lock(qe->chan);
4709  nativeformats = ao2_bump(ast_channel_nativeformats(qe->chan));
4710  ast_channel_unlock(qe->chan);
4711 
4712  /* Request the peer */
4713  tmp->chan = ast_request(tech, nativeformats, NULL, qe->chan, location, &status);
4714  ao2_cleanup(nativeformats);
4715  if (!tmp->chan) { /* If we can't, just go on to the next call */
4716  ao2_lock(qe->parent);
4717  qe->parent->rrpos++;
4718  qe->linpos++;
4719  ao2_unlock(qe->parent);
4720 
4721  pending_members_remove(tmp->member);
4722 
4723  publish_dial_end_event(qe->chan, tmp, NULL, "BUSY");
4724  tmp->stillgoing = 0;
4725  ++*busies;
4726  return 0;
4727  }
4728 
4729  ast_channel_lock_both(tmp->chan, qe->chan);
4730 
4733  if (qe->cancel_answered_elsewhere) {
4735  }
4736  ast_channel_appl_set(tmp->chan, "AppQueue");
4737  ast_channel_data_set(tmp->chan, "(Outgoing Line)");
4738  memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
4739 
4740  /* If the new channel has no callerid, try to guess what it should be */
4741  if (!ast_channel_caller(tmp->chan)->id.number.valid) {
4743  struct ast_party_caller caller;
4744 
4746  caller.id = ast_channel_connected(qe->chan)->id;
4747  caller.ani = ast_channel_connected(qe->chan)->ani;
4748  ast_channel_set_caller_event(tmp->chan, &caller, NULL);
4749  } else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
4753  }
4754  tmp->dial_callerid_absent = 1;
4755  }
4756 
4758 
4760 
4762 
4763  /* Inherit specially named variables from parent channel */
4767 
4768  /* Presense of ADSI CPE on outgoing channel follows ours */
4770 
4771  /* Inherit context and extension */
4772  macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
4773  ast_channel_dialcontext_set(tmp->chan, ast_strlen_zero(macrocontext) ? ast_channel_context(qe->chan) : macrocontext);
4774  macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
4775  if (!ast_strlen_zero(macroexten)) {
4776  ast_channel_exten_set(tmp->chan, macroexten);
4777  } else {
4779  }
4780 
4781  /* Save the original channel name to detect call pickup masquerading in. */
4782  tmp->orig_chan_name = ast_strdup(