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