Asterisk - The Open Source Telephony Project  21.4.1
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  *
45  * Patch Version 1.07 2003-12-24 01
46  *
47  * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
48  * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
49  *
50  * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
51  * by Matthew Enger <m.enger@xi.com.au>
52  *
53  * \ingroup applications
54  */
55 
56 /*! \li \ref app_queues.c uses configuration file \ref queues.conf
57  * \addtogroup configuration_file
58  */
59 
60 /*! \page queues.conf queues.conf
61  * \verbinclude queues.conf.sample
62  */
63 
64 /*** MODULEINFO
65  <support_level>core</support_level>
66  ***/
67 
68 #include "asterisk.h"
69 
70 #include <sys/time.h>
71 #include <signal.h>
72 #include <netinet/in.h>
73 #include <ctype.h>
74 
75 #include "asterisk/lock.h"
76 #include "asterisk/file.h"
77 #include "asterisk/channel.h"
78 #include "asterisk/pbx.h"
79 #include "asterisk/app.h"
80 #include "asterisk/linkedlists.h"
81 #include "asterisk/module.h"
82 #include "asterisk/translate.h"
83 #include "asterisk/say.h"
84 #include "asterisk/features.h"
85 #include "asterisk/musiconhold.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/manager.h"
88 #include "asterisk/config.h"
89 #include "asterisk/utils.h"
90 #include "asterisk/causes.h"
91 #include "asterisk/astdb.h"
92 #include "asterisk/devicestate.h"
93 #include "asterisk/stringfields.h"
94 #include "asterisk/astobj2.h"
95 #include "asterisk/strings.h"
96 #include "asterisk/taskprocessor.h"
97 #include "asterisk/aoc.h"
98 #include "asterisk/callerid.h"
99 #include "asterisk/term.h"
100 #include "asterisk/dial.h"
101 #include "asterisk/stasis_channels.h"
102 #include "asterisk/stasis_message_router.h"
103 #include "asterisk/bridge_after.h"
104 #include "asterisk/stasis_bridges.h"
105 #include "asterisk/core_local.h"
106 #include "asterisk/mixmonitor.h"
107 #include "asterisk/bridge_basic.h"
108 #include "asterisk/max_forwards.h"
109 
110 /*!
111  * \par Please read before modifying this file.
112  * There are three locks which are regularly used
113  * throughout this file, the queue list lock, the lock
114  * for each individual queue, and the interface list lock.
115  * Please be extra careful to always lock in the following order
116  * 1) queue list lock
117  * 2) individual queue lock
118  * 3) interface list lock
119  * This order has sort of "evolved" over the lifetime of this
120  * application, but it is now in place this way, so please adhere
121  * to this order!
122  */
123 
124 /*** DOCUMENTATION
125  <application name="Queue" language="en_US">
126  <synopsis>
127  Queue a call for a call queue.
128  </synopsis>
129  <syntax>
130  <parameter name="queuename" required="true" />
131  <parameter name="options">
132  <optionlist>
133  <option name="b" argsep="^">
134  <para>Before initiating an outgoing call, <literal>Gosub</literal> to the specified
135  location using the newly created channel. The <literal>Gosub</literal> will be
136  executed for each destination channel.</para>
137  <argument name="context" required="false" />
138  <argument name="exten" required="false" />
139  <argument name="priority" required="true" hasparams="optional" argsep="^">
140  <argument name="arg1" multiple="true" required="true" />
141  <argument name="argN" />
142  </argument>
143  </option>
144  <option name="B" argsep="^">
145  <para>Before initiating the outgoing call(s), <literal>Gosub</literal> to the
146  specified location using the current channel.</para>
147  <argument name="context" required="false" />
148  <argument name="exten" required="false" />
149  <argument name="priority" required="true" hasparams="optional" argsep="^">
150  <argument name="arg1" multiple="true" required="true" />
151  <argument name="argN" />
152  </argument>
153  </option>
154  <option name="C">
155  <para>Mark all calls as "answered elsewhere" when cancelled.</para>
156  </option>
157  <option name="c">
158  <para>Continue in the dialplan if the callee hangs up.</para>
159  </option>
160  <option name="d">
161  <para>Data-quality (modem) call (minimum delay).</para>
162  <para>This option only applies to DAHDI channels. By default,
163  DTMF is verified by muting audio TX/RX to verify the tone
164  is still present. This option disables that behavior.</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  <para>NOTE: Using this option from a GoSub() might not make sense as there would be no return points.</para>
175  </option>
176  <option name="h">
177  <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
178  </option>
179  <option name="H">
180  <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
181  </option>
182  <option name="i">
183  <para>Ignore call forward requests from queue members and do nothing
184  when they are requested.</para>
185  </option>
186  <option name="I">
187  <para>Asterisk will ignore any connected line update requests or any redirecting party
188  update requests it may receive on this dial attempt.</para>
189  </option>
190  <option name="k">
191  <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
192  the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
193  </option>
194  <option name="K">
195  <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
196  the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
197  </option>
198  <option name="m">
199  <para>Custom music on hold class to use, which will override the music on hold class configured
200  in <filename>queues.conf</filename>, if specified.</para>
201  <para>Note that CHANNEL(musicclass), if set, will still override this option.</para>
202  </option>
203  <option name="n">
204  <para>No retries on the timeout; will exit this application and
205  go to the next step.</para>
206  </option>
207  <option name="r">
208  <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
209  </option>
210  <option name="R">
211  <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
212  </option>
213  <option name="t">
214  <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
215  </option>
216  <option name="T">
217  <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
218  </option>
219  <option name="x">
220  <para>Allow the <emphasis>called</emphasis> user to write the conversation
221  to disk via MixMonitor.</para>
222  </option>
223  <option name="X">
224  <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
225  disk via MixMonitor.</para>
226  </option>
227  </optionlist>
228  </parameter>
229  <parameter name="URL">
230  <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
231  </parameter>
232  <parameter name="announceoverride" argsep="&amp;">
233  <para>Announcement file(s) to play to agent before bridging
234  call, overriding the announcement(s) configured in
235  <filename>queues.conf</filename>, if any.</para>
236  <para>Ampersand separated list of filenames. If the filename
237  is a relative filename (it does not begin with a slash), it
238  will be searched for in the Asterisk sounds directory. If the
239  filename is able to be parsed as a URL, Asterisk will
240  download the file and then begin playback on it. To include a
241  literal <literal>&amp;</literal> in the URL you can enclose
242  the URL in single quotes.</para>
243  <argument name="announceoverride" required="true" />
244  <argument name="announceoverride2" multiple="true" />
245  </parameter>
246  <parameter name="timeout">
247  <para>Will cause the queue to fail out after a specified number of
248  seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
249  <replaceable>retry</replaceable> cycle.</para>
250  </parameter>
251  <parameter name="AGI">
252  <para>Will setup an AGI script to be executed on the calling party's channel once they are
253  connected to a queue member.</para>
254  </parameter>
255  <parameter name="gosub">
256  <para>Will run a gosub on the called party's channel (the queue member)
257  once the parties are connected. The subroutine execution starts in the
258  named context at the s exten and priority 1.</para>
259  </parameter>
260  <parameter name="rule">
261  <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
262  </parameter>
263  <parameter name="position">
264  <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
265  would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
266  the caller third in the queue.</para>
267  </parameter>
268  </syntax>
269  <description>
270  <para>In addition to transferring the call, a call may be parked and then picked
271  up by another user.</para>
272  <para>This application will return to the dialplan if the queue does not exist, or
273  any of the join options cause the caller to not enter the queue.</para>
274  <para>This application does not automatically answer and should be preceeded
275  by an application such as Answer(), Progress(), or Ringing().</para>
276  <para>This application sets the following channel variables upon completion:</para>
277  <variablelist>
278  <variable name="QUEUESTATUS">
279  <para>The status of the call as a text string.</para>
280  <value name="TIMEOUT" />
281  <value name="FULL" />
282  <value name="JOINEMPTY" />
283  <value name="LEAVEEMPTY" />
284  <value name="JOINUNAVAIL" />
285  <value name="LEAVEUNAVAIL" />
286  <value name="CONTINUE" />
287  <value name="WITHDRAW" />
288  </variable>
289  <variable name="ABANDONED">
290  <para>If the call was not answered by an agent this variable will be TRUE.</para>
291  <value name="TRUE" />
292  </variable>
293  <variable name="DIALEDPEERNUMBER">
294  <para>Resource of the agent that was dialed set on the outbound channel.</para>
295  </variable>
296  <variable name="QUEUE_WITHDRAW_INFO">
297  <para>If the call was successfully withdrawn from the queue, and the withdraw request was provided with optional withdraw info, the withdraw info will be stored in this variable.</para>
298  </variable>
299  </variablelist>
300  </description>
301  <see-also>
302  <ref type="application">Queue</ref>
303  <ref type="application">QueueLog</ref>
304  <ref type="application">AddQueueMember</ref>
305  <ref type="application">RemoveQueueMember</ref>
306  <ref type="application">PauseQueueMember</ref>
307  <ref type="application">UnpauseQueueMember</ref>
308  <ref type="function">QUEUE_VARIABLES</ref>
309  <ref type="function">QUEUE_MEMBER</ref>
310  <ref type="function">QUEUE_MEMBER_COUNT</ref>
311  <ref type="function">QUEUE_EXISTS</ref>
312  <ref type="function">QUEUE_GET_CHANNEL</ref>
313  <ref type="function">QUEUE_WAITING_COUNT</ref>
314  <ref type="function">QUEUE_MEMBER_LIST</ref>
315  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
316  </see-also>
317  </application>
318  <application name="AddQueueMember" language="en_US">
319  <synopsis>
320  Dynamically adds queue members.
321  </synopsis>
322  <syntax>
323  <parameter name="queuename" required="true" />
324  <parameter name="interface" />
325  <parameter name="penalty" />
326  <parameter name="options" />
327  <parameter name="membername" />
328  <parameter name="stateinterface" />
329  <parameter name="wrapuptime" />
330  </syntax>
331  <description>
332  <para>Dynamically adds interface to an existing queue. If the interface is
333  already in the queue it will return an error.</para>
334  <para>This application sets the following channel variable upon completion:</para>
335  <variablelist>
336  <variable name="AQMSTATUS">
337  <para>The status of the attempt to add a queue member as a text string.</para>
338  <value name="ADDED" />
339  <value name="MEMBERALREADY" />
340  <value name="NOSUCHQUEUE" />
341  </variable>
342  </variablelist>
343  </description>
344  <see-also>
345  <ref type="application">Queue</ref>
346  <ref type="application">QueueLog</ref>
347  <ref type="application">AddQueueMember</ref>
348  <ref type="application">RemoveQueueMember</ref>
349  <ref type="application">PauseQueueMember</ref>
350  <ref type="application">UnpauseQueueMember</ref>
351  <ref type="function">QUEUE_VARIABLES</ref>
352  <ref type="function">QUEUE_MEMBER</ref>
353  <ref type="function">QUEUE_MEMBER_COUNT</ref>
354  <ref type="function">QUEUE_EXISTS</ref>
355  <ref type="function">QUEUE_GET_CHANNEL</ref>
356  <ref type="function">QUEUE_WAITING_COUNT</ref>
357  <ref type="function">QUEUE_MEMBER_LIST</ref>
358  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
359  </see-also>
360  </application>
361  <application name="RemoveQueueMember" language="en_US">
362  <synopsis>
363  Dynamically removes queue members.
364  </synopsis>
365  <syntax>
366  <parameter name="queuename" required="true" />
367  <parameter name="interface" />
368  </syntax>
369  <description>
370  <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
371  <para>This application sets the following channel variable upon completion:</para>
372  <variablelist>
373  <variable name="RQMSTATUS">
374  <value name="REMOVED" />
375  <value name="NOTINQUEUE" />
376  <value name="NOSUCHQUEUE" />
377  <value name="NOTDYNAMIC" />
378  </variable>
379  </variablelist>
380  <example title="Remove queue member">
381  same => n,RemoveQueueMember(techsupport,SIP/3000)
382  </example>
383  </description>
384  <see-also>
385  <ref type="application">Queue</ref>
386  <ref type="application">QueueLog</ref>
387  <ref type="application">AddQueueMember</ref>
388  <ref type="application">RemoveQueueMember</ref>
389  <ref type="application">PauseQueueMember</ref>
390  <ref type="application">UnpauseQueueMember</ref>
391  <ref type="function">QUEUE_VARIABLES</ref>
392  <ref type="function">QUEUE_MEMBER</ref>
393  <ref type="function">QUEUE_MEMBER_COUNT</ref>
394  <ref type="function">QUEUE_EXISTS</ref>
395  <ref type="function">QUEUE_GET_CHANNEL</ref>
396  <ref type="function">QUEUE_WAITING_COUNT</ref>
397  <ref type="function">QUEUE_MEMBER_LIST</ref>
398  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
399  </see-also>
400  </application>
401  <application name="PauseQueueMember" language="en_US">
402  <synopsis>
403  Pauses a queue member.
404  </synopsis>
405  <syntax>
406  <parameter name="queuename" />
407  <parameter name="interface" required="true" />
408  <parameter name="options" />
409  <parameter name="reason">
410  <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
411  </parameter>
412  </syntax>
413  <description>
414  <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
415  This prevents any calls from being sent from the queue to the interface until it is
416  unpaused with UnpauseQueueMember or the manager interface. If no queuename is given,
417  the interface is paused in every queue it is a member of. The application will fail if the
418  interface is not found.</para>
419  <para>This application sets the following channel variable upon completion:</para>
420  <variablelist>
421  <variable name="PQMSTATUS">
422  <para>The status of the attempt to pause a queue member as a text string.</para>
423  <value name="PAUSED" />
424  <value name="NOTFOUND" />
425  </variable>
426  </variablelist>
427  <example title="Pause queue member">
428  same => n,PauseQueueMember(,SIP/3000)
429  </example>
430  </description>
431  <see-also>
432  <ref type="application">Queue</ref>
433  <ref type="application">QueueLog</ref>
434  <ref type="application">AddQueueMember</ref>
435  <ref type="application">RemoveQueueMember</ref>
436  <ref type="application">PauseQueueMember</ref>
437  <ref type="application">UnpauseQueueMember</ref>
438  <ref type="function">QUEUE_VARIABLES</ref>
439  <ref type="function">QUEUE_MEMBER</ref>
440  <ref type="function">QUEUE_MEMBER_COUNT</ref>
441  <ref type="function">QUEUE_EXISTS</ref>
442  <ref type="function">QUEUE_GET_CHANNEL</ref>
443  <ref type="function">QUEUE_WAITING_COUNT</ref>
444  <ref type="function">QUEUE_MEMBER_LIST</ref>
445  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
446  </see-also>
447  </application>
448  <application name="UnpauseQueueMember" language="en_US">
449  <synopsis>
450  Unpauses a queue member.
451  </synopsis>
452  <syntax>
453  <parameter name="queuename" />
454  <parameter name="interface" required="true" />
455  <parameter name="options" />
456  <parameter name="reason">
457  <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
458  </parameter>
459  </syntax>
460  <description>
461  <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
462  and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
463  <para>This application sets the following channel variable upon completion:</para>
464  <variablelist>
465  <variable name="UPQMSTATUS">
466  <para>The status of the attempt to unpause a queue member as a text string.</para>
467  <value name="UNPAUSED" />
468  <value name="NOTFOUND" />
469  </variable>
470  </variablelist>
471  <example title="Unpause queue member">
472  same => n,UnpauseQueueMember(,SIP/3000)
473  </example>
474  </description>
475  <see-also>
476  <ref type="application">Queue</ref>
477  <ref type="application">QueueLog</ref>
478  <ref type="application">AddQueueMember</ref>
479  <ref type="application">RemoveQueueMember</ref>
480  <ref type="application">PauseQueueMember</ref>
481  <ref type="application">UnpauseQueueMember</ref>
482  <ref type="function">QUEUE_VARIABLES</ref>
483  <ref type="function">QUEUE_MEMBER</ref>
484  <ref type="function">QUEUE_MEMBER_COUNT</ref>
485  <ref type="function">QUEUE_EXISTS</ref>
486  <ref type="function">QUEUE_GET_CHANNEL</ref>
487  <ref type="function">QUEUE_WAITING_COUNT</ref>
488  <ref type="function">QUEUE_MEMBER_LIST</ref>
489  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
490  </see-also>
491  </application>
492  <application name="QueueLog" language="en_US">
493  <synopsis>
494  Writes to the queue_log file.
495  </synopsis>
496  <syntax>
497  <parameter name="queuename" required="true" />
498  <parameter name="uniqueid" required="true" />
499  <parameter name="agent" required="true" />
500  <parameter name="event" required="true" />
501  <parameter name="additionalinfo" />
502  </syntax>
503  <description>
504  <para>Allows you to write your own events into the queue log.</para>
505  <example title="Log custom queue event">
506  same => n,QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)
507  </example>
508  </description>
509  <see-also>
510  <ref type="application">Queue</ref>
511  <ref type="application">QueueLog</ref>
512  <ref type="application">AddQueueMember</ref>
513  <ref type="application">RemoveQueueMember</ref>
514  <ref type="application">PauseQueueMember</ref>
515  <ref type="application">UnpauseQueueMember</ref>
516  <ref type="function">QUEUE_VARIABLES</ref>
517  <ref type="function">QUEUE_MEMBER</ref>
518  <ref type="function">QUEUE_MEMBER_COUNT</ref>
519  <ref type="function">QUEUE_EXISTS</ref>
520  <ref type="function">QUEUE_GET_CHANNEL</ref>
521  <ref type="function">QUEUE_WAITING_COUNT</ref>
522  <ref type="function">QUEUE_MEMBER_LIST</ref>
523  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
524  </see-also>
525  </application>
526  <application name="QueueUpdate" language="en_US">
527  <synopsis>
528  Writes to the queue_log file for outbound calls and updates Realtime Data.
529  Is used at h extension to be able to have all the parameters.
530  </synopsis>
531  <syntax>
532  <parameter name="queuename" required="true" />
533  <parameter name="uniqueid" required="true" />
534  <parameter name="agent" required="true" />
535  <parameter name="status" required="true" />
536  <parameter name="talktime" required="true" />
537  <parameter name="params" required="false" />
538  </syntax>
539  <description>
540  <para>Allows you to write Outbound events into the queue log.</para>
541  <example title="Write outbound event into queue log">
542  exten => h,1,QueueUpdate(${QUEUE}, ${UNIQUEID}, ${AGENT}, ${DIALSTATUS}, ${ANSWEREDTIME}, ${DIALEDTIME} | ${DIALEDNUMBER})
543  </example>
544  </description>
545  </application>
546  <function name="QUEUE_VARIABLES" language="en_US">
547  <synopsis>
548  Return Queue information in variables.
549  </synopsis>
550  <syntax>
551  <parameter name="queuename" required="true">
552  <enumlist>
553  <enum name="QUEUEMAX">
554  <para>Maxmimum number of calls allowed.</para>
555  </enum>
556  <enum name="QUEUESTRATEGY">
557  <para>The strategy of the queue.</para>
558  </enum>
559  <enum name="QUEUECALLS">
560  <para>Number of calls currently in the queue.</para>
561  </enum>
562  <enum name="QUEUEHOLDTIME">
563  <para>Current average hold time.</para>
564  </enum>
565  <enum name="QUEUECOMPLETED">
566  <para>Number of completed calls for the queue.</para>
567  </enum>
568  <enum name="QUEUEABANDONED">
569  <para>Number of abandoned calls.</para>
570  </enum>
571  <enum name="QUEUESRVLEVEL">
572  <para>Queue service level.</para>
573  </enum>
574  <enum name="QUEUESRVLEVELPERF">
575  <para>Current service level performance.</para>
576  </enum>
577  </enumlist>
578  </parameter>
579  </syntax>
580  <description>
581  <para>Makes the following queue variables available.</para>
582  <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
583  </description>
584  <see-also>
585  <ref type="application">Queue</ref>
586  <ref type="application">QueueLog</ref>
587  <ref type="application">AddQueueMember</ref>
588  <ref type="application">RemoveQueueMember</ref>
589  <ref type="application">PauseQueueMember</ref>
590  <ref type="application">UnpauseQueueMember</ref>
591  <ref type="function">QUEUE_VARIABLES</ref>
592  <ref type="function">QUEUE_MEMBER</ref>
593  <ref type="function">QUEUE_MEMBER_COUNT</ref>
594  <ref type="function">QUEUE_EXISTS</ref>
595  <ref type="function">QUEUE_GET_CHANNEL</ref>
596  <ref type="function">QUEUE_WAITING_COUNT</ref>
597  <ref type="function">QUEUE_MEMBER_LIST</ref>
598  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
599  </see-also>
600  </function>
601  <function name="QUEUE_MEMBER" language="en_US">
602  <synopsis>
603  Provides a count of queue members based on the provided criteria, or updates a
604  queue member's settings.
605  </synopsis>
606  <syntax>
607  <parameter name="queuename" required="false" />
608  <parameter name="option" required="true">
609  <enumlist>
610  <enum name="logged">
611  <para>Returns the number of logged-in members for the specified queue.</para>
612  </enum>
613  <enum name="free">
614  <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>
615  </enum>
616  <enum name="ready">
617  <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
618  </enum>
619  <enum name="count">
620  <para>Returns the total number of members for the specified queue.</para>
621  </enum>
622  <enum name="penalty">
623  <para>Gets or sets queue member penalty. If
624  <replaceable>queuename</replaceable> is not specified
625  when setting the penalty then the penalty is set in all queues
626  the interface is a member.</para>
627  </enum>
628  <enum name="paused">
629  <para>Gets or sets queue member paused status. If
630  <replaceable>queuename</replaceable> is not specified
631  when setting the paused status then the paused status is set
632  in all queues the interface is a member.</para>
633  </enum>
634  <enum name="ringinuse">
635  <para>Gets or sets queue member ringinuse. If
636  <replaceable>queuename</replaceable> is not specified
637  when setting ringinuse then ringinuse is set
638  in all queues the interface is a member.</para>
639  </enum>
640  </enumlist>
641  </parameter>
642  <parameter name="interface" required="false" />
643  </syntax>
644  <description>
645  <para>Allows access to queue counts [R] and member information [R/W].</para>
646  <para><replaceable>queuename</replaceable> is required for all read operations.</para>
647  <para><replaceable>interface</replaceable> is required for all member operations.</para>
648  </description>
649  <see-also>
650  <ref type="application">Queue</ref>
651  <ref type="application">QueueLog</ref>
652  <ref type="application">AddQueueMember</ref>
653  <ref type="application">RemoveQueueMember</ref>
654  <ref type="application">PauseQueueMember</ref>
655  <ref type="application">UnpauseQueueMember</ref>
656  <ref type="function">QUEUE_VARIABLES</ref>
657  <ref type="function">QUEUE_MEMBER</ref>
658  <ref type="function">QUEUE_MEMBER_COUNT</ref>
659  <ref type="function">QUEUE_EXISTS</ref>
660  <ref type="function">QUEUE_GET_CHANNEL</ref>
661  <ref type="function">QUEUE_WAITING_COUNT</ref>
662  <ref type="function">QUEUE_MEMBER_LIST</ref>
663  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
664  </see-also>
665  </function>
666  <function name="QUEUE_MEMBER_COUNT" language="en_US">
667  <synopsis>
668  Count number of members answering a queue.
669  </synopsis>
670  <syntax>
671  <parameter name="queuename" required="true" />
672  </syntax>
673  <description>
674  <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
675  <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
676  </description>
677  <see-also>
678  <ref type="application">Queue</ref>
679  <ref type="application">QueueLog</ref>
680  <ref type="application">AddQueueMember</ref>
681  <ref type="application">RemoveQueueMember</ref>
682  <ref type="application">PauseQueueMember</ref>
683  <ref type="application">UnpauseQueueMember</ref>
684  <ref type="function">QUEUE_VARIABLES</ref>
685  <ref type="function">QUEUE_MEMBER</ref>
686  <ref type="function">QUEUE_MEMBER_COUNT</ref>
687  <ref type="function">QUEUE_EXISTS</ref>
688  <ref type="function">QUEUE_GET_CHANNEL</ref>
689  <ref type="function">QUEUE_WAITING_COUNT</ref>
690  <ref type="function">QUEUE_MEMBER_LIST</ref>
691  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
692  </see-also>
693  </function>
694  <function name="QUEUE_EXISTS" language="en_US">
695  <synopsis>
696  Check if a named queue exists on this server
697  </synopsis>
698  <syntax>
699  <parameter name="queuename" />
700  </syntax>
701  <description>
702  <para>Returns 1 if the specified queue exists, 0 if it does not</para>
703  </description>
704  <see-also>
705  <ref type="application">Queue</ref>
706  <ref type="application">QueueLog</ref>
707  <ref type="application">AddQueueMember</ref>
708  <ref type="application">RemoveQueueMember</ref>
709  <ref type="application">PauseQueueMember</ref>
710  <ref type="application">UnpauseQueueMember</ref>
711  <ref type="function">QUEUE_VARIABLES</ref>
712  <ref type="function">QUEUE_MEMBER</ref>
713  <ref type="function">QUEUE_MEMBER_COUNT</ref>
714  <ref type="function">QUEUE_EXISTS</ref>
715  <ref type="function">QUEUE_GET_CHANNEL</ref>
716  <ref type="function">QUEUE_WAITING_COUNT</ref>
717  <ref type="function">QUEUE_MEMBER_LIST</ref>
718  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
719  </see-also>
720  </function>
721  <function name="QUEUE_GET_CHANNEL" language="en_US">
722  <synopsis>
723  Return caller at the specified position in a queue.
724  </synopsis>
725  <syntax>
726  <parameter name="queuename" required="true" />
727  <parameter name="position" />
728  </syntax>
729  <description>
730  <para>Returns the caller channel at <replaceable>position</replaceable> in the specified <replaceable>queuename</replaceable>.</para>
731  <para>If <replaceable>position</replaceable> is unspecified the first channel is returned.</para>
732  </description>
733  <see-also>
734  <ref type="application">Queue</ref>
735  <ref type="application">QueueLog</ref>
736  <ref type="application">AddQueueMember</ref>
737  <ref type="application">RemoveQueueMember</ref>
738  <ref type="application">PauseQueueMember</ref>
739  <ref type="application">UnpauseQueueMember</ref>
740  <ref type="function">QUEUE_VARIABLES</ref>
741  <ref type="function">QUEUE_MEMBER</ref>
742  <ref type="function">QUEUE_MEMBER_COUNT</ref>
743  <ref type="function">QUEUE_EXISTS</ref>
744  <ref type="function">QUEUE_WAITING_COUNT</ref>
745  <ref type="function">QUEUE_MEMBER_LIST</ref>
746  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
747  </see-also>
748  </function>
749  <function name="QUEUE_WAITING_COUNT" language="en_US">
750  <synopsis>
751  Count number of calls currently waiting in a queue.
752  </synopsis>
753  <syntax>
754  <parameter name="queuename" />
755  </syntax>
756  <description>
757  <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
758  </description>
759  <see-also>
760  <ref type="application">Queue</ref>
761  <ref type="application">QueueLog</ref>
762  <ref type="application">AddQueueMember</ref>
763  <ref type="application">RemoveQueueMember</ref>
764  <ref type="application">PauseQueueMember</ref>
765  <ref type="application">UnpauseQueueMember</ref>
766  <ref type="function">QUEUE_VARIABLES</ref>
767  <ref type="function">QUEUE_MEMBER</ref>
768  <ref type="function">QUEUE_MEMBER_COUNT</ref>
769  <ref type="function">QUEUE_EXISTS</ref>
770  <ref type="function">QUEUE_GET_CHANNEL</ref>
771  <ref type="function">QUEUE_WAITING_COUNT</ref>
772  <ref type="function">QUEUE_MEMBER_LIST</ref>
773  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
774  </see-also>
775  </function>
776  <function name="QUEUE_MEMBER_LIST" language="en_US">
777  <synopsis>
778  Returns a list of interfaces on a queue.
779  </synopsis>
780  <syntax>
781  <parameter name="queuename" required="true" />
782  </syntax>
783  <description>
784  <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
785  </description>
786  <see-also>
787  <ref type="application">Queue</ref>
788  <ref type="application">QueueLog</ref>
789  <ref type="application">AddQueueMember</ref>
790  <ref type="application">RemoveQueueMember</ref>
791  <ref type="application">PauseQueueMember</ref>
792  <ref type="application">UnpauseQueueMember</ref>
793  <ref type="function">QUEUE_VARIABLES</ref>
794  <ref type="function">QUEUE_MEMBER</ref>
795  <ref type="function">QUEUE_MEMBER_COUNT</ref>
796  <ref type="function">QUEUE_EXISTS</ref>
797  <ref type="function">QUEUE_GET_CHANNEL</ref>
798  <ref type="function">QUEUE_WAITING_COUNT</ref>
799  <ref type="function">QUEUE_MEMBER_LIST</ref>
800  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
801  </see-also>
802  </function>
803  <function name="QUEUE_MEMBER_PENALTY" language="en_US">
804  <synopsis>
805  Gets or sets queue members penalty.
806  </synopsis>
807  <syntax>
808  <parameter name="queuename" required="true" />
809  <parameter name="interface" required="true" />
810  </syntax>
811  <description>
812  <para>Gets or sets queue members penalty.</para>
813  <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
814  </description>
815  <see-also>
816  <ref type="application">Queue</ref>
817  <ref type="application">QueueLog</ref>
818  <ref type="application">AddQueueMember</ref>
819  <ref type="application">RemoveQueueMember</ref>
820  <ref type="application">PauseQueueMember</ref>
821  <ref type="application">UnpauseQueueMember</ref>
822  <ref type="function">QUEUE_VARIABLES</ref>
823  <ref type="function">QUEUE_MEMBER</ref>
824  <ref type="function">QUEUE_MEMBER_COUNT</ref>
825  <ref type="function">QUEUE_EXISTS</ref>
826  <ref type="function">QUEUE_GET_CHANNEL</ref>
827  <ref type="function">QUEUE_WAITING_COUNT</ref>
828  <ref type="function">QUEUE_MEMBER_LIST</ref>
829  <ref type="function">QUEUE_MEMBER_PENALTY</ref>
830  </see-also>
831  </function>
832  <manager name="QueueStatus" language="en_US">
833  <synopsis>
834  Show queue status.
835  </synopsis>
836  <syntax>
837  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
838  <parameter name="Queue">
839  <para>Limit the response to the status of the specified queue.</para>
840  </parameter>
841  <parameter name="Member">
842  <para>Limit the response to the status of the specified member.</para>
843  </parameter>
844  </syntax>
845  <description>
846  <para>Check the status of one or more queues.</para>
847  </description>
848  </manager>
849  <manager name="QueueSummary" language="en_US">
850  <synopsis>
851  Show queue summary.
852  </synopsis>
853  <syntax>
854  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
855  <parameter name="Queue">
856  <para>Queue for which the summary is requested.</para>
857  </parameter>
858  </syntax>
859  <description>
860  <para>Request the manager to send a QueueSummary event.</para>
861  </description>
862  </manager>
863  <manager name="QueueAdd" language="en_US">
864  <synopsis>
865  Add interface to queue.
866  </synopsis>
867  <syntax>
868  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
869  <parameter name="Queue" required="true">
870  <para>Queue's name.</para>
871  </parameter>
872  <parameter name="Interface" required="true">
873  <para>The name of the interface (tech/name) to add to the queue.</para>
874  </parameter>
875  <parameter name="Penalty">
876  <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>
877  </parameter>
878  <parameter name="Paused">
879  <para>To pause or not the member initially (true/false or 1/0).</para>
880  </parameter>
881  <parameter name="MemberName">
882  <para>Text alias for the interface.</para>
883  </parameter>
884  <parameter name="StateInterface" />
885  </syntax>
886  <description>
887  </description>
888  </manager>
889  <manager name="QueueRemove" language="en_US">
890  <synopsis>
891  Remove interface from queue.
892  </synopsis>
893  <syntax>
894  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
895  <parameter name="Queue" required="true">
896  <para>The name of the queue to take action on.</para>
897  </parameter>
898  <parameter name="Interface" required="true">
899  <para>The interface (tech/name) to remove from queue.</para>
900  </parameter>
901  </syntax>
902  <description>
903  </description>
904  </manager>
905  <manager name="QueuePause" language="en_US">
906  <synopsis>
907  Makes a queue member temporarily unavailable.
908  </synopsis>
909  <syntax>
910  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
911  <parameter name="Interface" required="true">
912  <para>The name of the interface (tech/name) to pause or unpause.</para>
913  </parameter>
914  <parameter name="Paused" required="true">
915  <para>Pause or unpause the interface. Set to 'true' to pause the member or 'false' to unpause.</para>
916  </parameter>
917  <parameter name="Queue">
918  <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>
919  </parameter>
920  <parameter name="Reason">
921  <para>Text description, returned in the event QueueMemberPaused.</para>
922  </parameter>
923  </syntax>
924  <description>
925  <para>Pause or unpause a member in a queue.</para>
926  </description>
927  </manager>
928  <manager name="QueueLog" language="en_US">
929  <synopsis>
930  Adds custom entry in queue_log.
931  </synopsis>
932  <syntax>
933  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
934  <parameter name="Queue" required="true" />
935  <parameter name="Event" required="true" />
936  <parameter name="Uniqueid" />
937  <parameter name="Interface" />
938  <parameter name="Message" />
939  </syntax>
940  <description>
941  </description>
942  </manager>
943  <manager name="QueuePenalty" language="en_US">
944  <synopsis>
945  Set the penalty for a queue member.
946  </synopsis>
947  <syntax>
948  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
949  <parameter name="Interface" required="true">
950  <para>The interface (tech/name) of the member whose penalty to change.</para>
951  </parameter>
952  <parameter name="Penalty" required="true">
953  <para>The new penalty (number) for the member. Must be nonnegative.</para>
954  </parameter>
955  <parameter name="Queue">
956  <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>
957  </parameter>
958  </syntax>
959  <description>
960  <para>Change the penalty of a queue member</para>
961  </description>
962  </manager>
963  <manager name="QueueMemberRingInUse" language="en_US">
964  <synopsis>
965  Set the ringinuse value for a queue member.
966  </synopsis>
967  <syntax>
968  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
969  <parameter name="Interface" required="true" />
970  <parameter name="RingInUse" required="true" />
971  <parameter name="Queue" />
972  </syntax>
973  <description>
974  </description>
975  </manager>
976  <manager name="QueueRule" language="en_US">
977  <synopsis>
978  Queue Rules.
979  </synopsis>
980  <syntax>
981  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
982  <parameter name="Rule">
983  <para>The name of the rule in queuerules.conf whose contents to list.</para>
984  </parameter>
985  </syntax>
986  <description>
987  <para>List queue rules defined in queuerules.conf</para>
988  </description>
989  </manager>
990  <manager name="QueueReload" language="en_US">
991  <synopsis>
992  Reload a queue, queues, or any sub-section of a queue or queues.
993  </synopsis>
994  <syntax>
995  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
996  <parameter name="Queue">
997  <para>The name of the queue to take action on. If no queue name is specified, then all queues are affected.</para>
998  </parameter>
999  <parameter name="Members">
1000  <para>Whether to reload the queue's members.</para>
1001  <enumlist>
1002  <enum name="yes" />
1003  <enum name="no" />
1004  </enumlist>
1005  </parameter>
1006  <parameter name="Rules">
1007  <para>Whether to reload queuerules.conf</para>
1008  <enumlist>
1009  <enum name="yes" />
1010  <enum name="no" />
1011  </enumlist>
1012  </parameter>
1013  <parameter name="Parameters">
1014  <para>Whether to reload the other queue options.</para>
1015  <enumlist>
1016  <enum name="yes" />
1017  <enum name="no" />
1018  </enumlist>
1019  </parameter>
1020  </syntax>
1021  <description>
1022  </description>
1023  </manager>
1024  <manager name="QueueReset" language="en_US">
1025  <synopsis>
1026  Reset queue statistics.
1027  </synopsis>
1028  <syntax>
1029  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1030  <parameter name="Queue">
1031  <para>The name of the queue on which to reset statistics.</para>
1032  </parameter>
1033  </syntax>
1034  <description>
1035  <para>Reset the statistics for a queue.</para>
1036  </description>
1037  </manager>
1038  <manager name="QueueChangePriorityCaller" language="en_US">
1039  <synopsis>
1040  Change priority of a caller on queue.
1041  </synopsis>
1042  <syntax>
1043  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1044  <parameter name="Queue" required="true">
1045  <para>The name of the queue to take action on.</para>
1046  </parameter>
1047  <parameter name="Caller" required="true">
1048  <para>The caller (channel) to change priority on queue.</para>
1049  </parameter>
1050 
1051  <parameter name="Priority" required="true">
1052  <para>Priority value for change for caller on queue.</para>
1053  </parameter>
1054  <parameter name="Immediate">
1055  <para>When set to yes will cause the priority change to be reflected immediately, causing the channel to change position within the queue.</para>
1056  </parameter>
1057  </syntax>
1058  <description>
1059  </description>
1060  </manager>
1061  <manager name="QueueWithdrawCaller" language="en_US">
1062  <synopsis>
1063  Request to withdraw a caller from the queue back to the dialplan.
1064  </synopsis>
1065  <syntax>
1066  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1067  <parameter name="Queue" required="true">
1068  <para>The name of the queue to take action on.</para>
1069  </parameter>
1070  <parameter name="Caller" required="true">
1071  <para>The caller (channel) to withdraw from the queue.</para>
1072  </parameter>
1073  <parameter name="WithdrawInfo" required="false">
1074  <para>Optional info to store. If the call is successfully withdrawn from the queue, this information will be available in the QUEUE_WITHDRAW_INFO variable.</para>
1075  </parameter>
1076  </syntax>
1077  <description>
1078  </description>
1079  </manager>
1080 
1081  <managerEvent language="en_US" name="QueueParams">
1082  <managerEventInstance class="EVENT_FLAG_AGENT">
1083  <synopsis>Raised in response to the QueueStatus action.</synopsis>
1084  <syntax>
1085  <parameter name="Max">
1086  <para>The name of the queue.</para>
1087  </parameter>
1088  <parameter name="Strategy">
1089  <para>The strategy of the queue.</para>
1090  </parameter>
1091  <parameter name="Calls">
1092  <para>The queue member's channel technology or location.</para>
1093  </parameter>
1094  <parameter name="Holdtime">
1095  <para>The queue's hold time.</para>
1096  </parameter>
1097  <parameter name="TalkTime">
1098  <para>The queue's talk time.</para>
1099  </parameter>
1100  <parameter name="Completed">
1101  <para>The queue's completion time.</para>
1102  </parameter>
1103  <parameter name="Abandoned">
1104  <para>The queue's call abandonment metric.</para>
1105  </parameter>
1106  <parameter name="ServiceLevelPerf">
1107  <para>Primary service level performance metric.</para>
1108  </parameter>
1109  <parameter name="ServiceLevelPerf2">
1110  <para>Secondary service level performance metric.</para>
1111  </parameter>
1112  </syntax>
1113  <see-also>
1114  <ref type="managerEvent">QueueMember</ref>
1115  <ref type="managerEvent">QueueEntry</ref>
1116  </see-also>
1117  </managerEventInstance>
1118  </managerEvent>
1119  <managerEvent language="en_US" name="QueueEntry">
1120  <managerEventInstance class="EVENT_FLAG_AGENT">
1121  <synopsis>Raised in response to the QueueStatus action.</synopsis>
1122  <syntax>
1123  <parameter name="Queue">
1124  <para>The name of the queue.</para>
1125  </parameter>
1126  <parameter name="Position">
1127  <para>The caller's position within the queue.</para>
1128  </parameter>
1129  <parameter name="Channel">
1130  <para>The name of the caller's channel.</para>
1131  </parameter>
1132  <parameter name="Uniqueid">
1133  <para>The unique ID of the channel.</para>
1134  </parameter>
1135  <parameter name="CallerIDNum">
1136  <para>The Caller ID number.</para>
1137  </parameter>
1138  <parameter name="CallerIDName">
1139  <para>The Caller ID name.</para>
1140  </parameter>
1141  <parameter name="ConnectedLineNum">
1142  <para>The bridged party's number.</para>
1143  </parameter>
1144  <parameter name="ConnectedLineName">
1145  <para>The bridged party's name.</para>
1146  </parameter>
1147  <parameter name="Wait">
1148  <para>The caller's wait time.</para>
1149  </parameter>
1150  <parameter name="Priority">
1151  <para>The caller's priority within the queue.</para>
1152  </parameter>
1153  </syntax>
1154  <see-also>
1155  <ref type="managerEvent">QueueParams</ref>
1156  <ref type="managerEvent">QueueMember</ref>
1157  </see-also>
1158  </managerEventInstance>
1159  </managerEvent>
1160  <managerEvent language="en_US" name="QueueMemberStatus">
1161  <managerEventInstance class="EVENT_FLAG_AGENT">
1162  <synopsis>Raised when a Queue member's status has changed.</synopsis>
1163  <syntax>
1164  <parameter name="Queue">
1165  <para>The name of the queue.</para>
1166  </parameter>
1167  <parameter name="MemberName">
1168  <para>The name of the queue member.</para>
1169  </parameter>
1170  <parameter name="Interface">
1171  <para>The queue member's channel technology or location.</para>
1172  </parameter>
1173  <parameter name="StateInterface">
1174  <para>Channel technology or location from which to read device state changes.</para>
1175  </parameter>
1176  <parameter name="Membership">
1177  <enumlist>
1178  <enum name="dynamic"/>
1179  <enum name="realtime"/>
1180  <enum name="static"/>
1181  </enumlist>
1182  </parameter>
1183  <parameter name="Penalty">
1184  <para>The penalty associated with the queue member.</para>
1185  </parameter>
1186  <parameter name="CallsTaken">
1187  <para>The number of calls this queue member has serviced.</para>
1188  </parameter>
1189  <parameter name="LastCall">
1190  <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1191  </parameter>
1192  <parameter name="LastPause">
1193  <para>The time when started last paused the queue member.</para>
1194  </parameter>
1195  <parameter name="LoginTime">
1196  <para>The time this member logged in to the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1197  </parameter>
1198  <parameter name="InCall">
1199  <para>Set to 1 if member is in call. Set to 0 after LastCall time is updated.</para>
1200  <enumlist>
1201  <enum name="0"/>
1202  <enum name="1"/>
1203  </enumlist>
1204  </parameter>
1205  <parameter name="Status">
1206  <para>The numeric device state status of the queue member.</para>
1207  <enumlist>
1208  <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
1209  <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
1210  <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
1211  <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
1212  <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
1213  <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
1214  <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
1215  <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
1216  <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
1217  </enumlist>
1218  </parameter>
1219  <parameter name="Paused">
1220  <enumlist>
1221  <enum name="0"/>
1222  <enum name="1"/>
1223  </enumlist>
1224  </parameter>
1225  <parameter name="PausedReason">
1226  <para>If set when paused, the reason the queue member was paused.</para>
1227  </parameter>
1228  <parameter name="Ringinuse">
1229  <enumlist>
1230  <enum name="0"/>
1231  <enum name="1"/>
1232  </enumlist>
1233  </parameter>
1234  <parameter name="Wrapuptime">
1235  <para>The Wrapup Time of the queue member. If this value is set will override the wrapup time of queue.</para>
1236  </parameter>
1237  </syntax>
1238  </managerEventInstance>
1239  </managerEvent>
1240  <managerEvent language="en_US" name="QueueMemberAdded">
1241  <managerEventInstance class="EVENT_FLAG_AGENT">
1242  <synopsis>Raised when a member is added to the queue.</synopsis>
1243  <syntax>
1244  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1245  </syntax>
1246  <see-also>
1247  <ref type="managerEvent">QueueMemberRemoved</ref>
1248  <ref type="application">AddQueueMember</ref>
1249  </see-also>
1250  </managerEventInstance>
1251  </managerEvent>
1252  <managerEvent language="en_US" name="QueueMemberRemoved">
1253  <managerEventInstance class="EVENT_FLAG_AGENT">
1254  <synopsis>Raised when a member is removed from the queue.</synopsis>
1255  <syntax>
1256  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1257  </syntax>
1258  <see-also>
1259  <ref type="managerEvent">QueueMemberAdded</ref>
1260  <ref type="application">RemoveQueueMember</ref>
1261  </see-also>
1262  </managerEventInstance>
1263  </managerEvent>
1264  <managerEvent language="en_US" name="QueueMemberPause">
1265  <managerEventInstance class="EVENT_FLAG_AGENT">
1266  <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
1267  <syntax>
1268  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1269  </syntax>
1270  <see-also>
1271  <ref type="application">PauseQueueMember</ref>
1272  <ref type="application">UnpauseQueueMember</ref>
1273  </see-also>
1274  </managerEventInstance>
1275  </managerEvent>
1276  <managerEvent language="en_US" name="QueueMemberPenalty">
1277  <managerEventInstance class="EVENT_FLAG_AGENT">
1278  <synopsis>Raised when a member's penalty is changed.</synopsis>
1279  <syntax>
1280  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1281  </syntax>
1282  <see-also>
1283  <ref type="function">QUEUE_MEMBER</ref>
1284  </see-also>
1285  </managerEventInstance>
1286  </managerEvent>
1287  <managerEvent language="en_US" name="QueueMemberRinginuse">
1288  <managerEventInstance class="EVENT_FLAG_AGENT">
1289  <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
1290  <syntax>
1291  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1292  </syntax>
1293  <see-also>
1294  <ref type="function">QUEUE_MEMBER</ref>
1295  </see-also>
1296  </managerEventInstance>
1297  </managerEvent>
1298  <managerEvent language="en_US" name="QueueCallerJoin">
1299  <managerEventInstance class="EVENT_FLAG_AGENT">
1300  <synopsis>Raised when a caller joins a Queue.</synopsis>
1301  <syntax>
1302  <channel_snapshot/>
1303  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1304  <parameter name="Position">
1305  <para>This channel's current position in the queue.</para>
1306  </parameter>
1307  <parameter name="Count">
1308  <para>The total number of channels in the queue.</para>
1309  </parameter>
1310  </syntax>
1311  <see-also>
1312  <ref type="managerEvent">QueueCallerLeave</ref>
1313  <ref type="application">Queue</ref>
1314  </see-also>
1315  </managerEventInstance>
1316  </managerEvent>
1317  <managerEvent language="en_US" name="QueueCallerLeave">
1318  <managerEventInstance class="EVENT_FLAG_AGENT">
1319  <synopsis>Raised when a caller leaves a Queue.</synopsis>
1320  <syntax>
1321  <channel_snapshot/>
1322  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1323  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
1324  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1325  </syntax>
1326  <see-also>
1327  <ref type="managerEvent">QueueCallerJoin</ref>
1328  </see-also>
1329  </managerEventInstance>
1330  </managerEvent>
1331  <managerEvent language="en_US" name="QueueCallerAbandon">
1332  <managerEventInstance class="EVENT_FLAG_AGENT">
1333  <synopsis>Raised when a caller abandons the queue.</synopsis>
1334  <syntax>
1335  <channel_snapshot/>
1336  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1337  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1338  <parameter name="OriginalPosition">
1339  <para>The channel's original position in the queue.</para>
1340  </parameter>
1341  <parameter name="HoldTime">
1342  <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1343  </parameter>
1344  </syntax>
1345  </managerEventInstance>
1346  </managerEvent>
1347  <managerEvent language="en_US" name="AgentCalled">
1348  <managerEventInstance class="EVENT_FLAG_AGENT">
1349  <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
1350  <syntax>
1351  <channel_snapshot/>
1352  <channel_snapshot prefix="Dest"/>
1353  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1354  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1355  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1356  </syntax>
1357  <see-also>
1358  <ref type="managerEvent">AgentRingNoAnswer</ref>
1359  <ref type="managerEvent">AgentComplete</ref>
1360  <ref type="managerEvent">AgentConnect</ref>
1361  </see-also>
1362  </managerEventInstance>
1363  </managerEvent>
1364  <managerEvent language="en_US" name="AgentRingNoAnswer">
1365  <managerEventInstance class="EVENT_FLAG_AGENT">
1366  <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
1367  <syntax>
1368  <channel_snapshot/>
1369  <channel_snapshot prefix="Dest"/>
1370  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1371  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1372  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1373  <parameter name="RingTime">
1374  <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1375  </parameter>
1376  </syntax>
1377  <see-also>
1378  <ref type="managerEvent">AgentCalled</ref>
1379  </see-also>
1380  </managerEventInstance>
1381  </managerEvent>
1382  <managerEvent language="en_US" name="AgentComplete">
1383  <managerEventInstance class="EVENT_FLAG_AGENT">
1384  <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
1385  <syntax>
1386  <channel_snapshot/>
1387  <channel_snapshot prefix="Dest"/>
1388  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1389  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1390  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1391  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1392  <parameter name="TalkTime">
1393  <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1394  </parameter>
1395  <parameter name="Reason">
1396  <enumlist>
1397  <enum name="caller"/>
1398  <enum name="agent"/>
1399  <enum name="transfer"/>
1400  </enumlist>
1401  </parameter>
1402  </syntax>
1403  <see-also>
1404  <ref type="managerEvent">AgentCalled</ref>
1405  <ref type="managerEvent">AgentConnect</ref>
1406  </see-also>
1407  </managerEventInstance>
1408  </managerEvent>
1409  <managerEvent language="en_US" name="AgentDump">
1410  <managerEventInstance class="EVENT_FLAG_AGENT">
1411  <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
1412  <syntax>
1413  <channel_snapshot/>
1414  <channel_snapshot prefix="Dest"/>
1415  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1416  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1417  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1418  </syntax>
1419  <see-also>
1420  <ref type="managerEvent">AgentCalled</ref>
1421  <ref type="managerEvent">AgentConnect</ref>
1422  </see-also>
1423  </managerEventInstance>
1424  </managerEvent>
1425  <managerEvent language="en_US" name="AgentConnect">
1426  <managerEventInstance class="EVENT_FLAG_AGENT">
1427  <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
1428  <syntax>
1429  <channel_snapshot/>
1430  <channel_snapshot prefix="Dest"/>
1431  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1432  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1433  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1434  <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
1435  <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1436  </syntax>
1437  <see-also>
1438  <ref type="managerEvent">AgentCalled</ref>
1439  <ref type="managerEvent">AgentComplete</ref>
1440  <ref type="managerEvent">AgentDump</ref>
1441  </see-also>
1442  </managerEventInstance>
1443  </managerEvent>
1444  ***/
1445 
1446 enum {
1447  OPT_MARK_AS_ANSWERED = (1 << 0),
1448  OPT_GO_ON = (1 << 1),
1449  OPT_DATA_QUALITY = (1 << 2),
1450  OPT_CALLEE_GO_ON = (1 << 3),
1451  OPT_CALLEE_HANGUP = (1 << 4),
1452  OPT_CALLER_HANGUP = (1 << 5),
1453  OPT_IGNORE_CALL_FW = (1 << 6),
1454  OPT_IGNORE_CONNECTEDLINE = (1 << 7),
1455  OPT_CALLEE_PARK = (1 << 8),
1456  OPT_CALLER_PARK = (1 << 9),
1457  OPT_NO_RETRY = (1 << 10),
1458  OPT_RINGING = (1 << 11),
1459  OPT_RING_WHEN_RINGING = (1 << 12),
1460  OPT_CALLEE_TRANSFER = (1 << 13),
1461  OPT_CALLER_TRANSFER = (1 << 14),
1462  OPT_CALLEE_AUTOMIXMON = (1 << 15),
1463  OPT_CALLER_AUTOMIXMON = (1 << 16),
1464  OPT_CALLEE_AUTOMON = (1 << 17),
1465  OPT_CALLER_AUTOMON = (1 << 18),
1466  OPT_PREDIAL_CALLEE = (1 << 19),
1467  OPT_PREDIAL_CALLER = (1 << 20),
1468  OPT_MUSICONHOLD_CLASS = (1 << 21),
1469 };
1470 
1471 enum {
1472  OPT_ARG_CALLEE_GO_ON = 0,
1473  OPT_ARG_PREDIAL_CALLEE,
1474  OPT_ARG_PREDIAL_CALLER,
1475  OPT_ARG_MUSICONHOLD_CLASS,
1476  /* note: this entry _MUST_ be the last one in the enum */
1477  OPT_ARG_ARRAY_SIZE
1478 };
1479 
1480 AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
1481  AST_APP_OPTION_ARG('b', OPT_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE),
1482  AST_APP_OPTION_ARG('B', OPT_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER),
1483  AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
1484  AST_APP_OPTION('c', OPT_GO_ON),
1485  AST_APP_OPTION('d', OPT_DATA_QUALITY),
1486  AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
1487  AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
1488  AST_APP_OPTION('H', OPT_CALLER_HANGUP),
1489  AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
1490  AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
1491  AST_APP_OPTION('k', OPT_CALLEE_PARK),
1492  AST_APP_OPTION('K', OPT_CALLER_PARK),
1493  AST_APP_OPTION_ARG('m', OPT_MUSICONHOLD_CLASS, OPT_ARG_MUSICONHOLD_CLASS),
1494  AST_APP_OPTION('n', OPT_NO_RETRY),
1495  AST_APP_OPTION('r', OPT_RINGING),
1496  AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
1497  AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1498  AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
1499  AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
1500  AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
1501  AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
1502  AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
1503 END_OPTIONS);
1504 
1505 enum {
1506  QUEUE_STRATEGY_RINGALL = 0,
1507  QUEUE_STRATEGY_LEASTRECENT,
1508  QUEUE_STRATEGY_FEWESTCALLS,
1509  QUEUE_STRATEGY_RANDOM,
1510  QUEUE_STRATEGY_RRMEMORY,
1511  QUEUE_STRATEGY_LINEAR,
1512  QUEUE_STRATEGY_WRANDOM,
1513  QUEUE_STRATEGY_RRORDERED,
1514 };
1515 
1516 enum {
1517  QUEUE_AUTOPAUSE_OFF = 0,
1518  QUEUE_AUTOPAUSE_ON,
1519  QUEUE_AUTOPAUSE_ALL
1520 };
1521 
1522 enum queue_reload_mask {
1523  QUEUE_RELOAD_PARAMETERS = (1 << 0),
1524  QUEUE_RELOAD_MEMBER = (1 << 1),
1525  QUEUE_RELOAD_RULES = (1 << 2),
1526  QUEUE_RESET_STATS = (1 << 3),
1527 };
1528 
1529 static const struct strategy {
1530  int strategy;
1531  const char *name;
1532 } strategies[] = {
1533  { QUEUE_STRATEGY_RINGALL, "ringall" },
1534  { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
1535  { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
1536  { QUEUE_STRATEGY_RANDOM, "random" },
1537  { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
1538  { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
1539  { QUEUE_STRATEGY_LINEAR, "linear" },
1540  { QUEUE_STRATEGY_WRANDOM, "wrandom"},
1541  { QUEUE_STRATEGY_RRORDERED, "rrordered"},
1542 };
1543 
1544 static const struct autopause {
1545  int autopause;
1546  const char *name;
1547 } autopausesmodes [] = {
1548  { QUEUE_AUTOPAUSE_OFF,"no" },
1549  { QUEUE_AUTOPAUSE_ON, "yes" },
1550  { QUEUE_AUTOPAUSE_ALL,"all" },
1551 };
1552 
1553 #define DEFAULT_RETRY 5
1554 #define DEFAULT_TIMEOUT 15
1555 #define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
1556 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
1557 /*!
1558  * \brief The minimum number of seconds between position announcements.
1559  * \note The default value of 15 provides backwards compatibility.
1560  */
1561 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
1562 
1563 #define MAX_QUEUE_BUCKETS 53
1564 
1565 #define RES_OKAY 0 /*!< Action completed */
1566 #define RES_EXISTS (-1) /*!< Entry already exists */
1567 #define RES_OUTOFMEMORY (-2) /*!< Out of memory */
1568 #define RES_NOSUCHQUEUE (-3) /*!< No such queue */
1569 #define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
1570 #define RES_NOT_CALLER (-5) /*!< Caller not found */
1571 
1572 static char *app = "Queue";
1573 
1574 static char *app_aqm = "AddQueueMember" ;
1575 
1576 static char *app_rqm = "RemoveQueueMember" ;
1577 
1578 static char *app_pqm = "PauseQueueMember" ;
1579 
1580 static char *app_upqm = "UnpauseQueueMember" ;
1581 
1582 static char *app_ql = "QueueLog" ;
1583 
1584 static char *app_qupd = "QueueUpdate";
1585 
1586 /*! \brief Persistent Members astdb family */
1587 static const char * const pm_family = "Queue/PersistentMembers";
1588 
1589 /*! \brief queues.conf [general] option */
1591 
1592 /*! \brief Records that one or more queues use weight */
1593 static int use_weight;
1594 
1595 /*! \brief queues.conf [general] option */
1596 static int autofill_default;
1597 
1598 /*! \brief queues.conf [general] option */
1599 static int montype_default;
1600 
1601 /*! \brief queues.conf [general] option */
1602 static int shared_lastcall;
1603 
1604 /*! \brief queuerules.conf [general] option */
1605 static int realtime_rules;
1606 
1607 /*! \brief Subscription to device state change messages */
1609 
1610 /*! \brief queues.conf [general] option */
1612 
1613 /*! \brief queues.conf [general] option */
1615 
1616 /*! \brief queues.conf [general] option */
1618 
1619 /*! \brief name of the ringinuse field in the realtime database */
1621 
1622 /*! \brief does realtime backend support reason_paused */
1624 
1625 enum queue_result {
1626  QUEUE_UNKNOWN = 0,
1627  QUEUE_TIMEOUT = 1,
1628  QUEUE_JOINEMPTY = 2,
1629  QUEUE_LEAVEEMPTY = 3,
1630  QUEUE_JOINUNAVAIL = 4,
1631  QUEUE_LEAVEUNAVAIL = 5,
1632  QUEUE_FULL = 6,
1633  QUEUE_CONTINUE = 7,
1634  QUEUE_WITHDRAW = 8,
1635 };
1636 
1637 static const struct {
1638  enum queue_result id;
1639  char *text;
1640 } queue_results[] = {
1641  { QUEUE_UNKNOWN, "UNKNOWN" },
1642  { QUEUE_TIMEOUT, "TIMEOUT" },
1643  { QUEUE_JOINEMPTY,"JOINEMPTY" },
1644  { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
1645  { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
1646  { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
1647  { QUEUE_FULL, "FULL" },
1648  { QUEUE_CONTINUE, "CONTINUE" },
1649  { QUEUE_WITHDRAW, "WITHDRAW" },
1650 };
1651 
1652 enum queue_timeout_priority {
1653  TIMEOUT_PRIORITY_APP,
1654  TIMEOUT_PRIORITY_CONF,
1655 };
1656 
1657 /*! \brief We define a custom "local user" structure because we
1658  * use it not only for keeping track of what is in use but
1659  * also for keeping track of who we're dialing.
1660  *
1661  * There are two "links" defined in this structure, q_next and call_next.
1662  * q_next links ALL defined callattempt structures into a linked list. call_next is
1663  * a link which allows for a subset of the callattempts to be traversed. This subset
1664  * is used in wait_for_answer so that irrelevant callattempts are not traversed. This
1665  * also is helpful so that queue logs are always accurate in the case where a call to
1666  * a member times out, especially if using the ringall strategy.
1667 */
1668 
1669 struct callattempt {
1670  struct callattempt *q_next;
1671  struct callattempt *call_next;
1672  struct ast_channel *chan;
1673  char interface[256]; /*!< An Asterisk dial string (not a channel name) */
1674  int metric;
1675  struct member *member;
1676  /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
1678  /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
1680  /*! TRUE if the connected line update is blocked. */
1681  unsigned int block_connected_update:1;
1682  /*! TRUE if caller id is not available for connected line */
1683  unsigned int dial_callerid_absent:1;
1684  /*! TRUE if the call is still active */
1685  unsigned int stillgoing:1;
1686  struct ast_aoc_decoded *aoc_s_rate_list;
1687  /*! Original channel name. Must be freed. Could be NULL if allocation failed. */
1689 };
1690 
1691 
1692 struct queue_ent {
1693  struct call_queue *parent; /*!< What queue is our parent */
1694  char moh[MAX_MUSICCLASS]; /*!< Name of musiconhold to be used */
1695  char announce[PATH_MAX]; /*!< Announcement to play for member when call is answered */
1696  char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
1697  char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
1698  const char *predial_callee; /*!< Gosub app arguments for outgoing calls. NULL if not supplied. */
1699  int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
1700  int pos; /*!< Where we are in the queue */
1701  int prio; /*!< Our priority */
1702  int last_pos_said; /*!< Last position we told the user */
1703  int ring_when_ringing; /*!< Should we only use ring indication when a channel is ringing? */
1704  time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
1705  int last_periodic_announce_sound; /*!< The last periodic announcement we made */
1706  time_t last_pos; /*!< Last time we told the user their position */
1707  int opos; /*!< Where we started in the queue */
1708  int handled; /*!< Whether our call was handled */
1709  int pending; /*!< Non-zero if we are attempting to call a member */
1710  int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
1711  int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
1712  int raise_penalty; /*!< Float lower penalty members to a minimum penalty */
1713  int linpos; /*!< If using linear strategy, what position are we at? */
1714  int linwrapped; /*!< Is the linpos wrapped? */
1715  time_t start; /*!< When we started holding */
1716  time_t expire; /*!< When this entry should expire (time out of queue) */
1717  int cancel_answered_elsewhere; /*!< Whether we should force the CAE flag on this call (C) option*/
1718  unsigned int withdraw:1; /*!< Should this call exit the queue at its next iteration? Used for QueueWithdrawCaller */
1719  char *withdraw_info; /*!< Optional info passed by the caller of QueueWithdrawCaller */
1720  struct ast_channel *chan; /*!< Our channel */
1721  AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
1722  struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
1723  struct queue_ent *next; /*!< The next queue entry */
1724 };
1725 
1726 struct member {
1727  char interface[AST_CHANNEL_NAME]; /*!< Technology/Location to dial to reach this member*/
1728  char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
1729  char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
1730  char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
1731  int state_id; /*!< Extension state callback id (if using hint) */
1732  char membername[80]; /*!< Member name to use in queue logs */
1733  int penalty; /*!< Are we a last resort? */
1734  int calls; /*!< Number of calls serviced by this member */
1735  int dynamic; /*!< Are we dynamically added? */
1736  int realtime; /*!< Is this member realtime? */
1737  int status; /*!< Status of queue member */
1738  int paused; /*!< Are we paused (not accepting calls)? */
1739  char reason_paused[80]; /*!< Reason of paused if member is paused */
1740  int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */
1741  int callcompletedinsl; /*!< Whether the current call was completed within service level */
1742  int wrapuptime; /*!< Wrapup Time */
1743  time_t starttime; /*!< The time at which the member answered the current caller. */
1744  time_t lastcall; /*!< When last successful call was hungup */
1745  time_t lastpause; /*!< When started the last pause */
1746  time_t logintime; /*!< The time when started the login */
1747  struct call_queue *lastqueue; /*!< Last queue we received a call */
1748  unsigned int dead:1; /*!< Used to detect members deleted in realtime */
1749  unsigned int delme:1; /*!< Flag to delete entry on reload */
1750  char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
1751  unsigned int ringinuse:1; /*!< Flag to ring queue members even if their status is 'inuse' */
1752 };
1753 
1754 enum empty_conditions {
1755  QUEUE_EMPTY_PENALTY = (1 << 0),
1756  QUEUE_EMPTY_PAUSED = (1 << 1),
1757  QUEUE_EMPTY_INUSE = (1 << 2),
1758  QUEUE_EMPTY_RINGING = (1 << 3),
1759  QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
1760  QUEUE_EMPTY_INVALID = (1 << 5),
1761  QUEUE_EMPTY_UNKNOWN = (1 << 6),
1762  QUEUE_EMPTY_WRAPUP = (1 << 7),
1763 };
1764 
1765 enum member_properties {
1766  MEMBER_PENALTY = 0,
1767  MEMBER_RINGINUSE = 1,
1768 };
1769 
1770 /* values used in multi-bit flags in call_queue */
1771 #define ANNOUNCEHOLDTIME_ALWAYS 1
1772 #define ANNOUNCEHOLDTIME_ONCE 2
1773 #define QUEUE_EVENT_VARIABLES 3
1774 
1776  int time; /*!< Number of seconds that need to pass before applying this rule */
1777  int max_value; /*!< The amount specified in the penalty rule for max penalty */
1778  int min_value; /*!< The amount specified in the penalty rule for min penalty */
1779  int raise_value; /*!< The amount specified in the penalty rule for min penalty */
1780  int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
1781  int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
1782  int raise_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
1783  AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
1784 };
1785 
1786 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
1787 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
1788 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
1789 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
1790 
1791 struct call_queue {
1793  /*! Queue name */
1794  AST_STRING_FIELD(name);
1795  /*! Music on Hold class */
1796  AST_STRING_FIELD(moh);
1797  /*! Announcement to play when call is answered */
1798  AST_STRING_FIELD(announce);
1799  /*! Exit context */
1800  AST_STRING_FIELD(context);
1801  /*! Gosub to run upon member connection */
1802  AST_STRING_FIELD(membergosub);
1803  /*! Default rule to use if none specified in call to Queue() */
1804  AST_STRING_FIELD(defaultrule);
1805  /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
1806  AST_STRING_FIELD(sound_next);
1807  /*! Sound file: "There are currently" (def. queue-thereare) */
1808  AST_STRING_FIELD(sound_thereare);
1809  /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
1810  AST_STRING_FIELD(sound_calls);
1811  /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
1812  AST_STRING_FIELD(queue_quantity1);
1813  /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
1814  AST_STRING_FIELD(queue_quantity2);
1815  /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
1816  AST_STRING_FIELD(sound_holdtime);
1817  /*! Sound file: "minutes." (def. queue-minutes) */
1818  AST_STRING_FIELD(sound_minutes);
1819  /*! Sound file: "minute." (def. queue-minute) */
1820  AST_STRING_FIELD(sound_minute);
1821  /*! Sound file: "seconds." (def. queue-seconds) */
1822  AST_STRING_FIELD(sound_seconds);
1823  /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
1824  AST_STRING_FIELD(sound_thanks);
1825  /*! Sound file: Custom announce for caller, no default */
1826  AST_STRING_FIELD(sound_callerannounce);
1827  /*! Sound file: "Hold time" (def. queue-reporthold) */
1828  AST_STRING_FIELD(sound_reporthold);
1829  );
1830  /*! Sound files: Custom announce, no default */
1831  struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
1832  unsigned int dead:1;
1833  unsigned int ringinuse:1;
1834  unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
1835  unsigned int setinterfacevar:1;
1836  unsigned int setqueuevar:1;
1837  unsigned int setqueueentryvar:1;
1838  unsigned int reportholdtime:1;
1839  unsigned int wrapped:1;
1840  unsigned int timeoutrestart:1;
1841  unsigned int announceholdtime:2;
1842  unsigned int announceposition:3;
1843  unsigned int announceposition_only_up:1; /*!< Only announce position if it has improved */
1844  int strategy:4;
1845  unsigned int realtime:1;
1846  unsigned int found:1;
1847  unsigned int relativeperiodicannounce:1;
1848  unsigned int autopausebusy:1;
1849  unsigned int autopauseunavail:1;
1850  enum empty_conditions joinempty;
1851  enum empty_conditions leavewhenempty;
1852  int announcepositionlimit; /*!< How many positions we announce? */
1853  int announcefrequency; /*!< How often to announce their position */
1854  int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
1855  int periodicannouncestartdelay; /*!< How long into the queue should the periodic accouncement start */
1856  int periodicannouncefrequency; /*!< How often to play periodic announcement */
1857  int numperiodicannounce; /*!< The number of periodic announcements configured */
1858  int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
1859  int roundingseconds; /*!< How many seconds do we round to? */
1860  int holdtime; /*!< Current avg holdtime, based on an exponential average */
1861  int talktime; /*!< Current avg talktime, based on the same exponential average */
1862  int callscompleted; /*!< Number of queue calls completed */
1863  int callsabandoned; /*!< Number of queue calls abandoned */
1864  int callsabandonedinsl; /*!< Number of queue calls abandoned in servicelevel */
1865  int servicelevel; /*!< seconds setting for servicelevel*/
1866  int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
1867  char monfmt[8]; /*!< Format to use when recording calls */
1868  int count; /*!< How many entries */
1869  int maxlen; /*!< Max number of entries */
1870  int wrapuptime; /*!< Wrapup Time */
1871  int penaltymemberslimit; /*!< Disregard penalty when queue has fewer than this many members */
1872 
1873  int retry; /*!< Retry calling everyone after this amount of time */
1874  int timeout; /*!< How long to wait for an answer */
1875  int weight; /*!< Respective weight */
1876  int autopause; /*!< Auto pause queue members if they fail to answer */
1877  int autopausedelay; /*!< Delay auto pause for autopausedelay seconds since last call */
1878  int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
1879 
1880  /* Queue strategy things */
1881  int rrpos; /*!< Round Robin - position */
1882  int memberdelay; /*!< Seconds to delay connecting member to caller */
1883  int autofill; /*!< Ignore the head call status and ring an available agent */
1884 
1885  int log_restricted_caller_id:1; /*!< Whether log Restricted Caller ID */
1886 
1887  struct ao2_container *members; /*!< Head of the list of members */
1888  struct queue_ent *head; /*!< Head of the list of callers */
1889  AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
1890  AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
1891 };
1892 
1893 struct rule_list {
1894  char name[80];
1896  AST_LIST_ENTRY(rule_list) list;
1897 };
1898 
1900 
1901 static struct ao2_container *queues;
1902 
1903 static void update_realtime_members(struct call_queue *q);
1904 static struct member *interface_exists(struct call_queue *q, const char *interface);
1905 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
1906 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime);
1907 
1908 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
1909 /*! \brief sets the QUEUESTATUS channel variable */
1910 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
1911 {
1912  int i;
1913 
1914  for (i = 0; i < ARRAY_LEN(queue_results); i++) {
1915  if (queue_results[i].id == res) {
1916  pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
1917  return;
1918  }
1919  }
1920 }
1921 
1922 static const char *int2strat(int strategy)
1923 {
1924  int x;
1925 
1926  for (x = 0; x < ARRAY_LEN(strategies); x++) {
1927  if (strategy == strategies[x].strategy) {
1928  return strategies[x].name;
1929  }
1930  }
1931 
1932  return "<unknown>";
1933 }
1934 
1935 static int strat2int(const char *strategy)
1936 {
1937  int x;
1938 
1939  for (x = 0; x < ARRAY_LEN(strategies); x++) {
1940  if (!strcasecmp(strategy, strategies[x].name)) {
1941  return strategies[x].strategy;
1942  }
1943  }
1944 
1945  return -1;
1946 }
1947 
1948 static int autopause2int(const char *autopause)
1949 {
1950  int x;
1951  /*This 'double check' that default value is OFF */
1952  if (ast_strlen_zero(autopause)) {
1953  return QUEUE_AUTOPAUSE_OFF;
1954  }
1955 
1956  /*This 'double check' is to ensure old values works */
1957  if(ast_true(autopause)) {
1958  return QUEUE_AUTOPAUSE_ON;
1959  }
1960 
1961  for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1962  if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1963  return autopausesmodes[x].autopause;
1964  }
1965  }
1966 
1967  /*This 'double check' that default value is OFF */
1968  return QUEUE_AUTOPAUSE_OFF;
1969 }
1970 
1971 static int queue_hash_cb(const void *obj, const int flags)
1972 {
1973  const struct call_queue *q = obj;
1974 
1975  return ast_str_case_hash(q->name);
1976 }
1977 
1978 static int queue_cmp_cb(void *obj, void *arg, int flags)
1979 {
1980  struct call_queue *q = obj, *q2 = arg;
1981  return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1982 }
1983 
1984 /*!
1985  * \brief Return wrapuptime
1986  *
1987  * This function checks if wrapuptime in member is set and return this value.
1988  * Otherwise return value the wrapuptime in the queue configuration
1989  * \return integer value
1990  */
1991 static int get_wrapuptime(struct call_queue *q, struct member *member)
1992 {
1993  if (member->wrapuptime) {
1994  return member->wrapuptime;
1995  }
1996  return q->wrapuptime;
1997 }
1998 
1999 /*! \internal
2000  * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
2001  * \param obj the member being acted on
2002  * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
2003  * \param flag unused
2004  */
2005 static int queue_member_decrement_followers(void *obj, void *arg, int flag)
2006 {
2007  struct member *mem = obj;
2008  int *decrement_followers_after = arg;
2009 
2010  if (mem->queuepos > *decrement_followers_after) {
2011  mem->queuepos--;
2012  }
2013 
2014  return 0;
2015 }
2016 
2017 /*! \internal
2018  * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
2019  * on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
2020  * \param obj member being acted on
2021  * \param arg pointer to the queue members are being removed from
2022  * \param flag unused
2023  */
2024 static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
2025 {
2026  struct member *mem = obj;
2027  struct call_queue *queue = arg;
2028  int rrpos = mem->queuepos;
2029 
2030  if (mem->delme) {
2031  ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &rrpos);
2032  }
2033 
2034  return 0;
2035 }
2036 
2037 /*! \internal
2038  * \brief Use this to decrement followers during removal of a member
2039  * \param queue which queue the member is being removed from
2040  * \param mem which member is being removed from the queue
2041  */
2042 static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
2043 {
2044  int pos = mem->queuepos;
2045 
2046  /* 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
2047  * who would have been next otherwise. */
2048  if (pos < queue->rrpos) {
2049  queue->rrpos--;
2050  }
2051 
2052  ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
2053 }
2054 
2055 #define queue_ref(q) ao2_bump(q)
2056 #define queue_unref(q) ({ ao2_cleanup(q); NULL; })
2057 #define queue_t_ref(q, tag) ao2_t_bump(q, tag)
2058 #define queue_t_unref(q, tag) ({ ao2_t_cleanup(q, tag); NULL; })
2059 #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
2060 #define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
2061 
2062 /*! \brief Set variables of queue */
2063 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
2064 {
2065  char interfacevar[256]="";
2066  float sl = 0;
2067 
2068  ao2_lock(q);
2069 
2070  if (q->setqueuevar) {
2071  sl = 0;
2072  if (q->callscompleted > 0) {
2073  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
2074  }
2075 
2076  snprintf(interfacevar, sizeof(interfacevar),
2077  "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
2078  q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
2079 
2080  ao2_unlock(q);
2081 
2082  pbx_builtin_setvar_multiple(chan, interfacevar);
2083  } else {
2084  ao2_unlock(q);
2085  }
2086 }
2087 
2088 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
2089 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
2090 {
2091  struct queue_ent *cur;
2092 
2093  if (!q || !new)
2094  return;
2095  if (prev) {
2096  cur = prev->next;
2097  prev->next = new;
2098  } else {
2099  cur = q->head;
2100  q->head = new;
2101  }
2102  new->next = cur;
2103 
2104  /* every queue_ent must have a reference to it's parent call_queue, this
2105  * reference does not go away until the end of the queue_ent's life, meaning
2106  * that even when the queue_ent leaves the call_queue this ref must remain. */
2107  if (!new->parent) {
2108  queue_ref(q);
2109  new->parent = q;
2110  }
2111  new->pos = ++(*pos);
2112  new->opos = *pos;
2113 }
2114 
2115 static struct ast_manager_event_blob *queue_channel_to_ami(const char *type, struct stasis_message *message)
2116 {
2117  struct ast_channel_blob *obj = stasis_message_data(message);
2118  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
2119  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2120 
2121  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
2122  event_string = ast_manager_str_from_json_object(obj->blob, NULL);
2123  if (!channel_string || !event_string) {
2124  return NULL;
2125  }
2126 
2127  return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
2128  "%s"
2129  "%s",
2130  ast_str_buffer(channel_string),
2131  ast_str_buffer(event_string));
2132 }
2133 
2134 static struct ast_manager_event_blob *queue_caller_join_to_ami(struct stasis_message *message)
2135 {
2136  return queue_channel_to_ami("QueueCallerJoin", message);
2137 }
2138 
2139 static struct ast_manager_event_blob *queue_caller_leave_to_ami(struct stasis_message *message)
2140 {
2141  return queue_channel_to_ami("QueueCallerLeave", message);
2142 }
2143 
2144 static struct ast_manager_event_blob *queue_caller_abandon_to_ami(struct stasis_message *message)
2145 {
2146  return queue_channel_to_ami("QueueCallerAbandon", message);
2147 }
2148 
2149 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_join_type,
2150  .to_ami = queue_caller_join_to_ami,
2151  );
2152 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_leave_type,
2153  .to_ami = queue_caller_leave_to_ami,
2154  );
2155 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_abandon_type,
2156  .to_ami = queue_caller_abandon_to_ami,
2157  );
2158 
2159 static struct ast_manager_event_blob *queue_member_to_ami(const char *type, struct stasis_message *message)
2160 {
2161  struct ast_json_payload *payload = stasis_message_data(message);
2162  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2163 
2164  event_string = ast_manager_str_from_json_object(payload->json, NULL);
2165  if (!event_string) {
2166  return NULL;
2167  }
2168 
2169  return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
2170  "%s",
2171  ast_str_buffer(event_string));
2172 }
2173 
2174 static struct ast_manager_event_blob *queue_member_status_to_ami(struct stasis_message *message)
2175 {
2176  return queue_member_to_ami("QueueMemberStatus", message);
2177 }
2178 
2179 static struct ast_manager_event_blob *queue_member_added_to_ami(struct stasis_message *message)
2180 {
2181  return queue_member_to_ami("QueueMemberAdded", message);
2182 }
2183 
2184 static struct ast_manager_event_blob *queue_member_removed_to_ami(struct stasis_message *message)
2185 {
2186  return queue_member_to_ami("QueueMemberRemoved", message);
2187 }
2188 
2189 static struct ast_manager_event_blob *queue_member_pause_to_ami(struct stasis_message *message)
2190 {
2191  return queue_member_to_ami("QueueMemberPause", message);
2192 }
2193 
2194 static struct ast_manager_event_blob *queue_member_penalty_to_ami(struct stasis_message *message)
2195 {
2196  return queue_member_to_ami("QueueMemberPenalty", message);
2197 }
2198 
2199 static struct ast_manager_event_blob *queue_member_ringinuse_to_ami(struct stasis_message *message)
2200 {
2201  return queue_member_to_ami("QueueMemberRinginuse", message);
2202 }
2203 
2204 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_status_type,
2205  .to_ami = queue_member_status_to_ami,
2206  );
2207 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_added_type,
2208  .to_ami = queue_member_added_to_ami,
2209  );
2210 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_removed_type,
2211  .to_ami = queue_member_removed_to_ami,
2212  );
2213 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_pause_type,
2214  .to_ami = queue_member_pause_to_ami,
2215  );
2216 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_penalty_type,
2217  .to_ami = queue_member_penalty_to_ami,
2218  );
2219 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_ringinuse_type,
2220  .to_ami = queue_member_ringinuse_to_ami,
2221  );
2222 
2223 static struct ast_manager_event_blob *queue_multi_channel_to_ami(const char *type, struct stasis_message *message)
2224 {
2225  struct ast_multi_channel_blob *obj = stasis_message_data(message);
2226  struct ast_channel_snapshot *caller;
2227  struct ast_channel_snapshot *agent;
2228  RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
2229  RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
2230  RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2231 
2232  caller = ast_multi_channel_blob_get_channel(obj, "caller");
2233  if (caller) {
2234  caller_event_string = ast_manager_build_channel_state_string(caller);
2235  if (!caller_event_string) {
2236  ast_log(LOG_NOTICE, "No caller event string, bailing\n");
2237  return NULL;
2238  }
2239  }
2240 
2241  agent = ast_multi_channel_blob_get_channel(obj, "agent");
2242  if (agent) {
2243  agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
2244  if (!agent_event_string) {
2245  ast_log(LOG_NOTICE, "No agent event string, bailing\n");
2246  return NULL;
2247  }
2248  }
2249 
2251  if (!event_string) {
2252  return NULL;
2253  }
2254 
2255  return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
2256  "%s"
2257  "%s"
2258  "%s",
2259  caller_event_string ? ast_str_buffer(caller_event_string) : "",
2260  agent_event_string ? ast_str_buffer(agent_event_string) : "",
2261  ast_str_buffer(event_string));
2262 }
2263 
2264 static struct ast_manager_event_blob *queue_agent_called_to_ami(struct stasis_message *message)
2265 {
2266  return queue_multi_channel_to_ami("AgentCalled", message);
2267 }
2268 
2269 static struct ast_manager_event_blob *queue_agent_connect_to_ami(struct stasis_message *message)
2270 {
2271  return queue_multi_channel_to_ami("AgentConnect", message);
2272 }
2273 
2274 static struct ast_manager_event_blob *queue_agent_complete_to_ami(struct stasis_message *message)
2275 {
2276  return queue_multi_channel_to_ami("AgentComplete", message);
2277 }
2278 
2279 static struct ast_manager_event_blob *queue_agent_dump_to_ami(struct stasis_message *message)
2280 {
2281  return queue_multi_channel_to_ami("AgentDump", message);
2282 }
2283 
2284 static struct ast_manager_event_blob *queue_agent_ringnoanswer_to_ami(struct stasis_message *message)
2285 {
2286  return queue_multi_channel_to_ami("AgentRingNoAnswer", message);
2287 }
2288 
2289 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_called_type,
2290  .to_ami = queue_agent_called_to_ami,
2291  );
2292 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_connect_type,
2293  .to_ami = queue_agent_connect_to_ami,
2294  );
2295 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_complete_type,
2296  .to_ami = queue_agent_complete_to_ami,
2297  );
2298 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_dump_type,
2299  .to_ami = queue_agent_dump_to_ami,
2300  );
2301 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_ringnoanswer_type,
2302  .to_ami = queue_agent_ringnoanswer_to_ami,
2303  );
2304 
2305 static void queue_publish_multi_channel_snapshot_blob(struct stasis_topic *topic,
2306  struct ast_channel_snapshot *caller_snapshot,
2307  struct ast_channel_snapshot *agent_snapshot,
2308  struct stasis_message_type *type, struct ast_json *blob)
2309 {
2310  RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
2311  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
2312 
2313  if (!type) {
2314  return;
2315  }
2316 
2317  payload = ast_multi_channel_blob_create(blob);
2318  if (!payload) {
2319  return;
2320  }
2321 
2322  if (caller_snapshot) {
2323  ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
2324  } else {
2325  ast_debug(1, "Empty caller_snapshot; sending incomplete event\n");
2326  }
2327 
2328  if (agent_snapshot) {
2329  ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
2330  }
2331 
2332  msg = stasis_message_create(type, payload);
2333  if (!msg) {
2334  return;
2335  }
2336 
2337  stasis_publish(topic, msg);
2338 }
2339 
2340 static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent,
2341  struct stasis_message_type *type, struct ast_json *blob)
2342 {
2343  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
2344  RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
2345 
2346  ast_channel_lock(caller);
2347  caller_snapshot = ast_channel_snapshot_create(caller);
2348  ast_channel_unlock(caller);
2349  ast_channel_lock(agent);
2350  agent_snapshot = ast_channel_snapshot_create(agent);
2351  ast_channel_unlock(agent);
2352 
2353  if (!caller_snapshot || !agent_snapshot) {
2354  return;
2355  }
2356 
2357  queue_publish_multi_channel_snapshot_blob(ast_channel_topic(caller), caller_snapshot,
2358  agent_snapshot, type, blob);
2359 }
2360 
2361 /*!
2362  * \internal
2363  * \brief Publish the member blob.
2364  * \since 12.0.0
2365  *
2366  * \param type Stasis message type to publish.
2367  * \param blob The information being published.
2368  *
2369  * \note The json blob reference is passed to this function.
2370  */
2371 static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
2372 {
2373  RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
2374  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
2375 
2376  if (!blob || !type) {
2377  ast_json_unref(blob);
2378  return;
2379  }
2380 
2381  payload = ast_json_payload_create(blob);
2382  ast_json_unref(blob);
2383  if (!payload) {
2384  return;
2385  }
2386 
2387  msg = stasis_message_create(type, payload);
2388  if (!msg) {
2389  return;
2390  }
2391 
2393 }
2394 
2395 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
2396 {
2397  return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i, s: i}",
2398  "Queue", q->name,
2399  "MemberName", mem->membername,
2400  "Interface", mem->interface,
2401  "StateInterface", mem->state_interface,
2402  "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
2403  "Penalty", mem->penalty,
2404  "CallsTaken", mem->calls,
2405  "LastCall", (int)mem->lastcall,
2406  "LastPause", (int)mem->lastpause,
2407  "LoginTime", (int)mem->logintime,
2408  "InCall", mem->starttime ? 1 : 0,
2409  "Status", mem->status,
2410  "Paused", mem->paused,
2411  "PausedReason", mem->reason_paused,
2412  "Ringinuse", mem->ringinuse,
2413  "Wrapuptime", mem->wrapuptime);
2414 }
2415 
2416 /*! \brief Check if members are available
2417  *
2418  * This function checks to see if members are available to be called. If any member
2419  * is available, the function immediately returns 0. If no members are available,
2420  * then -1 is returned.
2421  */
2422 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, int raise_penalty, enum empty_conditions conditions, int devstate)
2423 {
2424  struct member *member;
2425  struct ao2_iterator mem_iter;
2426 
2427  ao2_lock(q);
2428  mem_iter = ao2_iterator_init(q->members, 0);
2429  for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
2430  int penalty = member->penalty;
2431  if (raise_penalty != INT_MAX && penalty < raise_penalty) {
2432  ast_debug(4, "%s is having his penalty raised up from %d to %d\n", member->membername, penalty, raise_penalty);
2433  penalty = raise_penalty;
2434  }
2435  if ((max_penalty != INT_MAX && penalty > max_penalty) || (min_penalty != INT_MAX && penalty < min_penalty)) {
2436  if (conditions & QUEUE_EMPTY_PENALTY) {
2437  ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
2438  continue;
2439  }
2440  }
2441 
2442  switch (devstate ? ast_device_state(member->state_interface) : member->status) {
2443  case AST_DEVICE_INVALID:
2444  if (conditions & QUEUE_EMPTY_INVALID) {
2445  ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
2446  break;
2447  }
2448  goto default_case;
2450  if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
2451  ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
2452  break;
2453  }
2454  goto default_case;
2455  case AST_DEVICE_INUSE:
2456  if (conditions & QUEUE_EMPTY_INUSE) {
2457  ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
2458  break;
2459  }
2460  goto default_case;
2461  case AST_DEVICE_RINGING:
2462  if (conditions & QUEUE_EMPTY_RINGING) {
2463  ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
2464  break;
2465  }
2466  goto default_case;
2467  case AST_DEVICE_UNKNOWN:
2468  if (conditions & QUEUE_EMPTY_UNKNOWN) {
2469  ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
2470  break;
2471  }
2472  /* Fall-through */
2473  default:
2474  default_case:
2475  if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
2476  ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
2477  break;
2478  } else if ((conditions & QUEUE_EMPTY_WRAPUP)
2479  && member->lastcall
2480  && get_wrapuptime(q, member)
2481  && (time(NULL) - get_wrapuptime(q, member) < member->lastcall)) {
2482  ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n",
2483  member->membername, (int) (time(NULL) - member->lastcall), get_wrapuptime(q, member));
2484  break;
2485  } else {
2486  ao2_ref(member, -1);
2487  ao2_iterator_destroy(&mem_iter);
2488  ao2_unlock(q);
2489  ast_debug(4, "%s is available.\n", member->membername);
2490  return 0;
2491  }
2492  break;
2493  }
2494  }
2495  ao2_iterator_destroy(&mem_iter);
2496  ao2_unlock(q);
2497 
2498  if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
2499  /* member state still may be RINGING due to lag in event message - check again with device state */
2500  return get_member_status(q, max_penalty, min_penalty, raise_penalty, conditions, 1);
2501  }
2502  return -1;
2503 }
2504 
2505 /*
2506  * A "pool" of member objects that calls are currently pending on. If an
2507  * agent is a member of multiple queues it's possible for that agent to be
2508  * called by each of the queues at the same time. This happens because device
2509  * state is slow to notify the queue app of one of it's member's being rung.
2510  * This "pool" allows us to track which members are currently being rung while
2511  * we wait on the device state change.
2512  */
2513 static struct ao2_container *pending_members;
2514 #define MAX_CALL_ATTEMPT_BUCKETS 353
2515 
2516 static int pending_members_hash(const void *obj, const int flags)
2517 {
2518  const struct member *object;
2519  const char *key;
2520 
2521  switch (flags & OBJ_SEARCH_MASK) {
2522  case OBJ_SEARCH_KEY:
2523  key = obj;
2524  break;
2525  case OBJ_SEARCH_OBJECT:
2526  object = obj;
2527  key = object->interface;
2528  break;
2529  default:
2530  ast_assert(0);
2531  return 0;
2532  }
2533  return ast_str_case_hash(key);
2534 }
2535 
2536 static int pending_members_cmp(void *obj, void *arg, int flags)
2537 {
2538  const struct member *object_left = obj;
2539  const struct member *object_right = arg;
2540  const char *right_key = arg;
2541  int cmp;
2542 
2543  switch (flags & OBJ_SEARCH_MASK) {
2544  case OBJ_SEARCH_OBJECT:
2545  right_key = object_right->interface;
2546  /* Fall through */
2547  case OBJ_SEARCH_KEY:
2548  cmp = strcasecmp(object_left->interface, right_key);
2549  break;
2551  /* Not supported by container. */
2552  ast_assert(0);
2553  return 0;
2554  default:
2555  cmp = 0;
2556  break;
2557  }
2558  if (cmp) {
2559  return 0;
2560  }
2561  return CMP_MATCH;
2562 }
2563 
2564 static void pending_members_remove(struct member *mem)
2565 {
2566  ast_debug(3, "Removed %s from pending_members\n", mem->membername);
2567  ao2_find(pending_members, mem, OBJ_POINTER | OBJ_NODATA | OBJ_UNLINK);
2568 }
2569 
2570 /*! \brief set a member's status based on device state of that member's state_interface.
2571  *
2572  * Lock interface list find sc, iterate through each queues queue_member list for member to
2573  * update state inside queues
2574 */
2575 static void update_status(struct call_queue *q, struct member *m, const int status)
2576 {
2577  if (m->status != status) {
2578  /* If this member has transitioned to being available then update their queue
2579  * information. If they are currently in a call then the leg to the agent will be
2580  * considered done and the call finished.
2581  */
2582  if (status == AST_DEVICE_NOT_INUSE) {
2584  }
2585 
2586  m->status = status;
2587 
2588  /* Remove the member from the pending members pool only when the status changes.
2589  * This is not done unconditionally because we can occasionally see multiple
2590  * device state notifications of not in use after a previous call has ended,
2591  * including after we have initiated a new call. This is more likely to
2592  * happen when there is latency in the connection to the member.
2593  */
2594  pending_members_remove(m);
2595 
2596  queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
2597  }
2598 }
2599 
2600 /*!
2601  * \internal
2602  * \brief Determine if a queue member is available
2603  * \retval 1 if the member is available
2604  * \retval 0 if the member is not available
2605  */
2606 static int is_member_available(struct call_queue *q, struct member *mem)
2607 {
2608  int available = 0;
2609  int wrapuptime;
2610 
2611  switch (mem->status) {
2612  case AST_DEVICE_INVALID:
2614  break;
2615  case AST_DEVICE_INUSE:
2616  case AST_DEVICE_BUSY:
2617  case AST_DEVICE_RINGING:
2618  case AST_DEVICE_RINGINUSE:
2619  case AST_DEVICE_ONHOLD:
2620  if (!mem->ringinuse) {
2621  break;
2622  }
2623  /* else fall through */
2624  case AST_DEVICE_NOT_INUSE:
2625  case AST_DEVICE_UNKNOWN:
2626  if (!mem->paused) {
2627  available = 1;
2628  }
2629  break;
2630  }
2631 
2632  /* Let wrapuptimes override device state availability */
2633  wrapuptime = get_wrapuptime(q, mem);
2634  if (mem->lastcall && wrapuptime && (time(NULL) - wrapuptime < mem->lastcall)) {
2635  available = 0;
2636  }
2637  return available;
2638 }
2639 
2640 /*! \brief set a member's status based on device state of that member's interface*/
2641 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
2642 {
2643  struct ao2_iterator miter, qiter;
2644  struct ast_device_state_message *dev_state;
2645  struct member *m;
2646  struct call_queue *q;
2647  char interface[80], *slash_pos;
2648  int found = 0; /* Found this member in any queue */
2649  int found_member; /* Found this member in this queue */
2650  int avail = 0; /* Found an available member in this queue */
2651 
2653  return;
2654  }
2655 
2656  dev_state = stasis_message_data(msg);
2657  if (dev_state->eid) {
2658  /* ignore non-aggregate states */
2659  return;
2660  }
2661 
2662  qiter = ao2_iterator_init(queues, 0);
2663  while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2664  ao2_lock(q);
2665 
2666  avail = 0;
2667  found_member = 0;
2668  miter = ao2_iterator_init(q->members, 0);
2669  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2670  if (!found_member) {
2671  ast_copy_string(interface, m->state_interface, sizeof(interface));
2672 
2673  if ((slash_pos = strchr(interface, '/'))) {
2674  if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2675  *slash_pos = '\0';
2676  }
2677  }
2678 
2679  if (!strcasecmp(interface, dev_state->device)) {
2680  found_member = 1;
2681  update_status(q, m, dev_state->state);
2682  }
2683  }
2684 
2685  /* check every member until we find one NOT_INUSE */
2686  if (!avail) {
2687  avail = is_member_available(q, m);
2688  }
2689  if (avail && found_member) {
2690  /* early exit as we've found an available member and the member of interest */
2691  ao2_ref(m, -1);
2692  break;
2693  }
2694  }
2695 
2696  if (found_member) {
2697  found = 1;
2698  if (avail) {
2700  } else {
2702  }
2703  }
2704 
2705  ao2_iterator_destroy(&miter);
2706 
2707  ao2_unlock(q);
2708  queue_t_unref(q, "Done with iterator");
2709  }
2710  ao2_iterator_destroy(&qiter);
2711 
2712  if (found) {
2713  ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
2714  dev_state->device,
2715  dev_state->state,
2716  ast_devstate2str(dev_state->state));
2717  } else {
2718  ast_debug(3, "Device '%s' changed to state '%u' (%s) but we don't care because they're not a member of any queue.\n",
2719  dev_state->device,
2720  dev_state->state,
2721  ast_devstate2str(dev_state->state));
2722  }
2723 
2724  return;
2725 }
2726 
2727 /*! \brief Helper function which converts from extension state to device state values */
2729 {
2730  switch (state) {
2732  state = AST_DEVICE_NOT_INUSE;
2733  break;
2734  case AST_EXTENSION_INUSE:
2735  state = AST_DEVICE_INUSE;
2736  break;
2737  case AST_EXTENSION_BUSY:
2738  state = AST_DEVICE_BUSY;
2739  break;
2740  case AST_EXTENSION_RINGING:
2741  state = AST_DEVICE_RINGING;
2742  break;
2744  state = AST_DEVICE_RINGINUSE;
2745  break;
2746  case AST_EXTENSION_ONHOLD:
2747  state = AST_DEVICE_ONHOLD;
2748  break;
2750  state = AST_DEVICE_INUSE;
2751  break;
2753  state = AST_DEVICE_UNAVAILABLE;
2754  break;
2755  case AST_EXTENSION_REMOVED:
2757  default:
2758  state = AST_DEVICE_INVALID;
2759  break;
2760  }
2761 
2762  return state;
2763 }
2764 
2765 /*!
2766  * \brief Returns if one context includes another context
2767  *
2768  * \param parent Parent context to search for child
2769  * \param child Context to check for inclusion in parent
2770  *
2771  * This function recursively checks if the context child is included in the context parent.
2772  *
2773  * \retval 1 if child is included in parent
2774  * \retval 0 if not
2775  */
2776 static int context_included(const char *parent, const char *child);
2777 static int context_included(const char *parent, const char *child)
2778 {
2779  struct ast_context *c = NULL;
2780 
2781  c = ast_context_find(parent);
2782  if (!c) {
2783  /* well, if parent doesn't exist, how can the child be included in it? */
2784  return 0;
2785  }
2786  if (!strcmp(ast_get_context_name(c), parent)) {
2787  /* found the context of the hint app_queue is using. Now, see
2788  if that context includes the one that just changed state */
2789  struct ast_include *inc = NULL;
2790 
2791  while ((inc = (struct ast_include*) ast_walk_context_includes(c, inc))) {
2792  const char *includename = ast_get_include_name(inc);
2793  if (!strcasecmp(child, includename)) {
2794  return 1;
2795  }
2796  /* recurse on this context, for nested includes. The
2797  PBX extension parser will prevent infinite recursion. */
2798  if (context_included(includename, child)) {
2799  return 1;
2800  }
2801  }
2802  }
2803  return 0;
2804 }
2805 
2806 static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
2807 {
2808  struct ao2_iterator miter, qiter;
2809  struct member *m;
2810  struct call_queue *q;
2811  int state = info->exten_state;
2812  int found = 0, device_state = extensionstate2devicestate(state);
2813 
2814  /* only interested in extension state updates involving device states */
2815  if (info->reason != AST_HINT_UPDATE_DEVICE) {
2816  return 0;
2817  }
2818 
2819  qiter = ao2_iterator_init(queues, 0);
2820  while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2821  ao2_lock(q);
2822 
2823  miter = ao2_iterator_init(q->members, 0);
2824  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2825  if (!strcmp(m->state_exten, exten) &&
2826  (!strcmp(m->state_context, context) || context_included(m->state_context, context))) {
2827  /* context could be included in m->state_context. We need to check. */
2828  found = 1;
2829  update_status(q, m, device_state);
2830  }
2831  }
2832  ao2_iterator_destroy(&miter);
2833 
2834  ao2_unlock(q);
2835  queue_t_unref(q, "Done with iterator");
2836  }
2837  ao2_iterator_destroy(&qiter);
2838 
2839  if (found) {
2840  ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2841  } else {
2842  ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
2843  exten, context, device_state, ast_devstate2str(device_state));
2844  }
2845 
2846  return 0;
2847 }
2848 
2849 /*! \brief Return the current state of a member */
2850 static int get_queue_member_status(struct member *cur)
2851 {
2853 }
2854 
2855 static void destroy_queue_member_cb(void *obj)
2856 {
2857  struct member *mem = obj;
2858 
2859  if (mem->state_id != -1) {
2860  ast_extension_state_del(mem->state_id, extension_state_cb);
2861  }
2862 }
2863 
2864 /*! \brief allocate space for new queue member and set fields based on parameters passed */
2865 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse, int wrapuptime)
2866 {
2867  struct member *cur;
2868 
2869  if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
2870  cur->ringinuse = ringinuse;
2871  cur->penalty = penalty;
2872  cur->paused = paused;
2873  cur->wrapuptime = wrapuptime;
2874  if (paused) {
2875  time(&cur->lastpause); /* Update time of last pause */
2876  }
2877  time(&cur->logintime);
2878  ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2879  if (!ast_strlen_zero(state_interface)) {
2880  ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
2881  } else {
2882  ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
2883  }
2884  if (!ast_strlen_zero(membername)) {
2885  ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2886  } else {
2887  ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2888  }
2889  if (!strchr(cur->interface, '/')) {
2890  ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2891  }
2892  if (!strncmp(cur->state_interface, "hint:", 5)) {
2893  char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2894  char *exten = strsep(&context, "@") + 5;
2895 
2896  ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2897  ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2898 
2899  cur->state_id = ast_extension_state_add(cur->state_context, cur->state_exten, extension_state_cb, NULL);
2900  } else {
2901  cur->state_id = -1;
2902  }
2903  cur->status = get_queue_member_status(cur);
2904  }
2905 
2906  return cur;
2907 }
2908 
2909 
2910 static int compress_char(const char c)
2911 {
2912  if (c < 32) {
2913  return 0;
2914  } else if (c > 96) {
2915  return c - 64;
2916  }
2917  return c - 32;
2918 }
2919 
2920 static int member_hash_fn(const void *obj, const int flags)
2921 {
2922  const struct member *mem = obj;
2923  const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
2924  const char *chname = strchr(interface, '/');
2925  int ret = 0, i;
2926 
2927  if (!chname) {
2928  chname = interface;
2929  }
2930  for (i = 0; i < 5 && chname[i]; i++) {
2931  ret += compress_char(chname[i]) << (i * 6);
2932  }
2933  return ret;
2934 }
2935 
2936 static int member_cmp_fn(void *obj1, void *obj2, int flags)
2937 {
2938  struct member *mem1 = obj1;
2939  struct member *mem2 = obj2;
2940  const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
2941 
2942  return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
2943 }
2944 
2945 /*!
2946  * \brief Initialize Queue default values.
2947  * \note the queue's lock must be held before executing this function
2948 */
2949 static void init_queue(struct call_queue *q)
2950 {
2951  int i;
2952  struct penalty_rule *pr_iter;
2953 
2954  q->dead = 0;
2955  q->retry = DEFAULT_RETRY;
2956  q->timeout = DEFAULT_TIMEOUT;
2957  q->maxlen = 0;
2958 
2959  ast_string_field_set(q, announce, "");
2960  ast_string_field_set(q, context, "");
2961  ast_string_field_set(q, membergosub, "");
2962  ast_string_field_set(q, defaultrule, "");
2963 
2964  q->announcefrequency = 0;
2966  q->announceholdtime = 1;
2967  q->announceposition_only_up = 0;
2968  q->announcepositionlimit = 10; /* Default 10 positions */
2969  q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
2970  q->roundingseconds = 0; /* Default - don't announce seconds */
2971  q->servicelevel = 0;
2972  q->ringinuse = 1;
2973  q->announce_to_first_user = 0;
2974  q->setinterfacevar = 0;
2975  q->setqueuevar = 0;
2976  q->setqueueentryvar = 0;
2978  q->monfmt[0] = '\0';
2979  q->reportholdtime = 0;
2980  q->wrapuptime = 0;
2981  q->penaltymemberslimit = 0;
2982  q->joinempty = 0;
2983  q->leavewhenempty = 0;
2984  q->memberdelay = 0;
2985  q->weight = 0;
2986  q->timeoutrestart = 0;
2989  q->randomperiodicannounce = 0;
2990  q->numperiodicannounce = 0;
2991  q->relativeperiodicannounce = 0;
2992  q->autopause = QUEUE_AUTOPAUSE_OFF;
2993  q->autopausebusy = 0;
2994  q->autopauseunavail = 0;
2995  q->timeoutpriority = TIMEOUT_PRIORITY_APP;
2996  q->autopausedelay = 0;
2997  q->log_restricted_caller_id = 1;
2998  if (!q->members) {
2999  if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
3000  /* linear strategy depends on order, so we have to place all members in a list */
3001  q->members = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, member_cmp_fn);
3002  } else {
3004  member_hash_fn, NULL, member_cmp_fn);
3005  }
3006  }
3007  q->found = 1;
3008 
3009  ast_string_field_set(q, moh, "");
3010  ast_string_field_set(q, sound_next, "queue-youarenext");
3011  ast_string_field_set(q, sound_thereare, "queue-thereare");
3012  ast_string_field_set(q, sound_calls, "queue-callswaiting");
3013  ast_string_field_set(q, queue_quantity1, "queue-quantity1");
3014  ast_string_field_set(q, queue_quantity2, "queue-quantity2");
3015  ast_string_field_set(q, sound_holdtime, "queue-holdtime");
3016  ast_string_field_set(q, sound_minutes, "queue-minutes");
3017  ast_string_field_set(q, sound_minute, "queue-minute");
3018  ast_string_field_set(q, sound_seconds, "queue-seconds");
3019  ast_string_field_set(q, sound_thanks, "queue-thankyou");
3020  ast_string_field_set(q, sound_callerannounce, "");
3021  ast_string_field_set(q, sound_reporthold, "queue-reporthold");
3022 
3023  if (!q->sound_periodicannounce[0]) {
3025  }
3026 
3027  if (q->sound_periodicannounce[0]) {
3028  ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
3029  }
3030 
3031  for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3032  if (q->sound_periodicannounce[i]) {
3033  ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
3034  }
3035  }
3036 
3037  while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
3038  ast_free(pr_iter);
3039  }
3040 
3041  /* On restart assume no members are available.
3042  * The queue_avail hint is a boolean state to indicate whether a member is available or not.
3043  *
3044  * This seems counter intuitive, but is required to light a BLF
3045  * AST_DEVICE_INUSE indicates no members are available.
3046  * AST_DEVICE_NOT_INUSE indicates a member is available.
3047  */
3049 }
3050 
3051 static void clear_queue(struct call_queue *q)
3052 {
3053  q->holdtime = 0;
3054  q->callscompleted = 0;
3055  q->callsabandoned = 0;
3056  q->callscompletedinsl = 0;
3057  q->callsabandonedinsl = 0;
3058  q->talktime = 0;
3059 
3060  if (q->members) {
3061  struct member *mem;
3062  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3063  while ((mem = ao2_iterator_next(&mem_iter))) {
3064  mem->calls = 0;
3065  mem->callcompletedinsl = 0;
3066  mem->lastcall = 0;
3067  mem->starttime = 0;
3068  ao2_ref(mem, -1);
3069  }
3070  ao2_iterator_destroy(&mem_iter);
3071  }
3072 }
3073 
3074 /*!
3075  * \brief Change queue penalty by adding rule.
3076  *
3077  * Check rule for errors with time or formatting, see if rule is relative to rest
3078  * of queue, iterate list of rules to find correct insertion point, insert and return.
3079  * \retval -1 on failure
3080  * \retval 0 on success
3081  * \note Call this with the rule_lists locked
3082 */
3083 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
3084 {
3085  char *timestr, *maxstr, *minstr, *raisestr, *contentdup;
3086  struct penalty_rule *rule = NULL, *rule_iter;
3087  struct rule_list *rl_iter;
3088  int penaltychangetime, inserted = 0;
3089 
3090  if (!(rule = ast_calloc(1, sizeof(*rule)))) {
3091  return -1;
3092  }
3093 
3094  contentdup = ast_strdupa(content);
3095 
3096  if (!(maxstr = strchr(contentdup, ','))) {
3097  ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
3098  ast_free(rule);
3099  return -1;
3100  }
3101 
3102  *maxstr++ = '\0';
3103  if ((minstr = strchr(maxstr,','))) {
3104  *minstr++ = '\0';
3105  if ((raisestr = strchr(minstr,','))) {
3106  *raisestr++ = '\0';
3107  }
3108  } else {
3109  raisestr = NULL;
3110  }
3111 
3112  timestr = contentdup;
3113  if ((penaltychangetime = atoi(timestr)) < 0) {
3114  ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
3115  ast_free(rule);
3116  return -1;
3117  }
3118 
3119  rule->time = penaltychangetime;
3120 
3121  /* The last check will evaluate true if either no penalty change is indicated for a given rule
3122  * OR if a min penalty change is indicated but no max penalty change is */
3123  if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
3124  rule->max_relative = 1;
3125  }
3126 
3127  rule->max_value = atoi(maxstr);
3128 
3129  if (!ast_strlen_zero(minstr)) {
3130  if (*minstr == '+' || *minstr == '-') {
3131  rule->min_relative = 1;
3132  }
3133  rule->min_value = atoi(minstr);
3134  } else { /*there was no minimum specified, so assume this means no change*/
3135  rule->min_relative = 1;
3136  }
3137 
3138  if (!ast_strlen_zero(raisestr)) {
3139  if (*raisestr == '+' || *raisestr == '-') {
3140  rule->raise_relative = 1;
3141  }
3142  rule->raise_value = atoi(raisestr);
3143  } else { /*there was no raise specified, so assume this means no change*/
3144  rule->raise_relative = 1;
3145  }
3146 
3147  /*We have the rule made, now we need to insert it where it belongs*/
3148  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
3149  if (strcasecmp(rl_iter->name, list_name)) {
3150  continue;
3151  }
3152 
3153  AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
3154  if (rule->time < rule_iter->time) {
3155  AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
3156  inserted = 1;
3157  break;
3158  }
3159  }
3161 
3162  if (!inserted) {
3163  AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
3164  inserted = 1;
3165  }
3166 
3167  break;
3168  }
3169 
3170  if (!inserted) {
3171  ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
3172  ast_free(rule);
3173  return -1;
3174  }
3175  return 0;
3176 }
3177 
3178 /*!
3179  * \brief Load queue rules from realtime.
3180  *
3181  * Check rule for errors with time or formatting, see if rule is relative to rest
3182  * of queue, iterate list of rules to find correct insertion point, insert and return.
3183  * \retval -1 on failure
3184  * \retval 0 on success
3185  * \note Call this with the rule_lists locked
3186 */
3187 static int load_realtime_rules(void)
3188 {
3189  struct ast_config *cfg;
3190  struct rule_list *rl_iter, *new_rl;
3191  struct penalty_rule *pr_iter;
3192  char *rulecat = NULL;
3193 
3194  if (!ast_check_realtime("queue_rules")) {
3195  ast_log(LOG_WARNING, "Missing \"queue_rules\" in extconfig.conf\n");
3196  return 0;
3197  }
3198  if (!(cfg = ast_load_realtime_multientry("queue_rules", "rule_name LIKE", "%", SENTINEL))) {
3199  ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n");
3200  return 0;
3201  }
3202  while ((rulecat = ast_category_browse(cfg, rulecat))) {
3203  const char *timestr, *maxstr, *minstr, *raisestr, *rule_name;
3204  int penaltychangetime, rule_exists = 0, inserted = 0;
3205  int max_penalty = 0, min_penalty = 0, raise_penalty = 0;
3206  int min_relative = 0, max_relative = 0, raise_relative = 0;
3207  struct penalty_rule *new_penalty_rule = NULL;
3208 
3209  rule_name = ast_variable_retrieve(cfg, rulecat, "rule_name");
3210  if (ast_strlen_zero(rule_name)) {
3211  continue;
3212  }
3213 
3214  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
3215  if (!(strcasecmp(rl_iter->name, rule_name))) {
3216  rule_exists = 1;
3217  new_rl = rl_iter;
3218  break;
3219  }
3220  }
3221  if (!rule_exists) {
3222  if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
3223  ast_config_destroy(cfg);
3224  return -1;
3225  }
3226  ast_copy_string(new_rl->name, rule_name, sizeof(new_rl->name));
3227  AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
3228  }
3229  timestr = ast_variable_retrieve(cfg, rulecat, "time");
3230  if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) {
3231  ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules, skipping it\n",
3232  (ast_strlen_zero(timestr) ? "invalid value" : timestr), rule_name);
3233  continue;
3234  }
3235  if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) {
3236  ast_config_destroy(cfg);
3237  return -1;
3238  }
3239  if (!(maxstr = ast_variable_retrieve(cfg, rulecat, "max_penalty")) ||
3240  ast_strlen_zero(maxstr) || sscanf(maxstr, "%30d", &max_penalty) != 1) {
3241  max_penalty = 0;
3242  max_relative = 1;
3243  } else {
3244  if (*maxstr == '+' || *maxstr == '-') {
3245  max_relative = 1;
3246  }
3247  }
3248  if (!(minstr = ast_variable_retrieve(cfg, rulecat, "min_penalty")) ||
3249  ast_strlen_zero(minstr) || sscanf(minstr, "%30d", &min_penalty) != 1) {
3250  min_penalty = 0;
3251  min_relative = 1;
3252  } else {
3253  if (*minstr == '+' || *minstr == '-') {
3254  min_relative = 1;
3255  }
3256  }
3257  if (!(raisestr = ast_variable_retrieve(cfg, rulecat, "raise_penalty")) ||
3258  ast_strlen_zero(raisestr) || sscanf(raisestr, "%30d", &raise_penalty) != 1) {
3259  raise_penalty = 0;
3260  raise_relative = 1;
3261  } else {
3262  if (*raisestr == '+' || *raisestr == '-') {
3263  raise_relative = 1;
3264  }
3265  }
3266  new_penalty_rule->time = penaltychangetime;
3267  new_penalty_rule->max_relative = max_relative;
3268  new_penalty_rule->max_value = max_penalty;
3269  new_penalty_rule->min_relative = min_relative;
3270  new_penalty_rule->min_value = min_penalty;
3271  new_penalty_rule->raise_relative = raise_relative;
3272  new_penalty_rule->raise_value = raise_penalty;
3273  AST_LIST_TRAVERSE_SAFE_BEGIN(&new_rl->rules, pr_iter, list) {
3274  if (new_penalty_rule->time < pr_iter->time) {
3275  AST_LIST_INSERT_BEFORE_CURRENT(new_penalty_rule, list);
3276  inserted = 1;
3277  }
3278  }
3280  if (!inserted) {
3281  AST_LIST_INSERT_TAIL(&new_rl->rules, new_penalty_rule, list);
3282  }
3283  }
3284 
3285  ast_config_destroy(cfg);
3286  return 0;
3287 }
3288 
3289 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
3290 {
3291  char *value_copy = ast_strdupa(value);
3292  char *option = NULL;
3293  while ((option = strsep(&value_copy, ","))) {
3294  if (!strcasecmp(option, "paused")) {
3295  *empty |= QUEUE_EMPTY_PAUSED;
3296  } else if (!strcasecmp(option, "penalty")) {
3297  *empty |= QUEUE_EMPTY_PENALTY;
3298  } else if (!strcasecmp(option, "inuse")) {
3299  *empty |= QUEUE_EMPTY_INUSE;
3300  } else if (!strcasecmp(option, "ringing")) {
3301  *empty |= QUEUE_EMPTY_RINGING;
3302  } else if (!strcasecmp(option, "invalid")) {
3303  *empty |= QUEUE_EMPTY_INVALID;
3304  } else if (!strcasecmp(option, "wrapup")) {
3305  *empty |= QUEUE_EMPTY_WRAPUP;
3306  } else if (!strcasecmp(option, "unavailable")) {
3307  *empty |= QUEUE_EMPTY_UNAVAILABLE;
3308  } else if (!strcasecmp(option, "unknown")) {
3309  *empty |= QUEUE_EMPTY_UNKNOWN;
3310  } else if (!strcasecmp(option, "loose")) {
3311  *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
3312  } else if (!strcasecmp(option, "strict")) {
3313  *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
3314  } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
3315  *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
3316  } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
3317  *empty = 0;
3318  } else {
3319  ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
3320  }
3321  }
3322 }
3323 
3324 /*! \brief Configure a queue parameter.
3325  *
3326  * The failunknown flag is set for config files (and static realtime) to show
3327  * errors for unknown parameters. It is cleared for dynamic realtime to allow
3328  * extra fields in the tables.
3329  * \note For error reporting, line number is passed for .conf static configuration,
3330  * for Realtime queues, linenum is -1.
3331 */
3332 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
3333 {
3334  if (!strcasecmp(param, "musicclass") ||
3335  !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
3336  ast_string_field_set(q, moh, val);
3337  } else if (!strcasecmp(param, "announce")) {
3338  ast_string_field_set(q, announce, val);
3339  } else if (!strcasecmp(param, "context")) {
3340  ast_string_field_set(q, context, val);
3341  } else if (!strcasecmp(param, "timeout")) {
3342  q->timeout = atoi(val);
3343  if (q->timeout < 0) {
3344  q->timeout = DEFAULT_TIMEOUT;
3345  }
3346  } else if (!strcasecmp(param, "ringinuse")) {
3347  q->ringinuse = ast_true(val);
3348  } else if (!strcasecmp(param, "setinterfacevar")) {
3349  q->setinterfacevar = ast_true(val);
3350  } else if (!strcasecmp(param, "setqueuevar")) {
3351  q->setqueuevar = ast_true(val);
3352  } else if (!strcasecmp(param, "setqueueentryvar")) {
3353  q->setqueueentryvar = ast_true(val);
3354  } else if (!strcasecmp(param, "monitor-format")) {
3355  ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
3356  } else if (!strcasecmp(param, "membergosub")) {
3357  ast_string_field_set(q, membergosub, val);
3358  } else if (!strcasecmp(param, "queue-youarenext")) {
3359  ast_string_field_set(q, sound_next, val);
3360  } else if (!strcasecmp(param, "queue-thereare")) {
3361  ast_string_field_set(q, sound_thereare, val);
3362  } else if (!strcasecmp(param, "queue-callswaiting")) {
3363  ast_string_field_set(q, sound_calls, val);
3364  } else if (!strcasecmp(param, "queue-quantity1")) {
3365  ast_string_field_set(q, queue_quantity1, val);
3366  } else if (!strcasecmp(param, "queue-quantity2")) {
3367  ast_string_field_set(q, queue_quantity2, val);
3368  } else if (!strcasecmp(param, "queue-holdtime")) {
3369  ast_string_field_set(q, sound_holdtime, val);
3370  } else if (!strcasecmp(param, "queue-minutes")) {
3371  ast_string_field_set(q, sound_minutes, val);
3372  } else if (!strcasecmp(param, "queue-minute")) {
3373  ast_string_field_set(q, sound_minute, val);
3374  } else if (!strcasecmp(param, "queue-seconds")) {
3375  ast_string_field_set(q, sound_seconds, val);
3376  } else if (!strcasecmp(param, "queue-thankyou")) {
3377  ast_string_field_set(q, sound_thanks, val);
3378  } else if (!strcasecmp(param, "queue-callerannounce")) {
3379  ast_string_field_set(q, sound_callerannounce, val);
3380  } else if (!strcasecmp(param, "queue-reporthold")) {
3381  ast_string_field_set(q, sound_reporthold, val);
3382  } else if (!strcasecmp(param, "announce-frequency")) {
3383  q->announcefrequency = atoi(val);
3384  } else if (!strcasecmp(param, "announce-to-first-user")) {
3385  q->announce_to_first_user = ast_true(val);
3386  } else if (!strcasecmp(param, "min-announce-frequency")) {
3387  q->minannouncefrequency = atoi(val);
3388  ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
3389  } else if (!strcasecmp(param, "announce-round-seconds")) {
3390  q->roundingseconds = atoi(val);
3391  /* Rounding to any other values just doesn't make sense... */
3392  if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
3393  || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
3394  if (linenum >= 0) {
3395  ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
3396  "using 0 instead for queue '%s' at line %d of queues.conf\n",
3397  val, param, q->name, linenum);
3398  } else {
3399  ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
3400  "using 0 instead for queue '%s'\n", val, param, q->name);
3401  }
3402  q->roundingseconds=0;
3403  }
3404  } else if (!strcasecmp(param, "announce-holdtime")) {
3405  if (!strcasecmp(val, "once")) {
3406  q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
3407  } else if (ast_true(val)) {
3408  q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
3409  } else {
3410  q->announceholdtime = 0;
3411  }
3412  } else if (!strcasecmp(param, "announce-position")) {
3413  if (!strcasecmp(val, "limit")) {
3414  q->announceposition = ANNOUNCEPOSITION_LIMIT;
3415  } else if (!strcasecmp(val, "more")) {
3416  q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
3417  } else if (ast_true(val)) {
3418  q->announceposition = ANNOUNCEPOSITION_YES;
3419  } else {
3420  q->announceposition = ANNOUNCEPOSITION_NO;
3421  }
3422  } else if (!strcasecmp(param, "announce-position-only-up")) {
3424  } else if (!strcasecmp(param, "announce-position-limit")) {
3425  q->announcepositionlimit = atoi(val);
3426  } else if (!strcasecmp(param, "periodic-announce")) {
3427  if (strchr(val, ',')) {
3428  char *s, *buf = ast_strdupa(val);
3429  unsigned int i = 0;
3430 
3431  while ((s = strsep(&buf, ",|"))) {
3432  if (!q->sound_periodicannounce[i]) {
3434  }
3435  ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
3436  i++;
3437  if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
3438  break;
3439  }
3440  }
3441  q->numperiodicannounce = i;
3442  } else {
3443  ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
3444  q->numperiodicannounce = 1;
3445  }
3446  } else if (!strcasecmp(param, "periodic-announce-startdelay")) {
3447  q->periodicannouncestartdelay = atoi(val);
3448  } else if (!strcasecmp(param, "periodic-announce-frequency")) {
3449  q->periodicannouncefrequency = atoi(val);
3450  } else if (!strcasecmp(param, "relative-periodic-announce")) {
3451  q->relativeperiodicannounce = ast_true(val);
3452  } else if (!strcasecmp(param, "random-periodic-announce")) {
3453  q->randomperiodicannounce = ast_true(val);
3454  } else if (!strcasecmp(param, "retry")) {
3455  q->retry = atoi(val);
3456  if (q->retry <= 0) {
3457  q->retry = DEFAULT_RETRY;
3458  }
3459  } else if (!strcasecmp(param, "wrapuptime")) {
3460  q->wrapuptime = atoi(val);
3461  } else if (!strcasecmp(param, "penaltymemberslimit")) {
3462  if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
3463  q->penaltymemberslimit = 0;
3464  }
3465  } else if (!strcasecmp(param, "autofill")) {
3466  q->autofill = ast_true(val);
3467  } else if (!strcasecmp(param, "autopause")) {
3468  q->autopause = autopause2int(val);
3469  } else if (!strcasecmp(param, "autopausedelay")) {
3470  q->autopausedelay = atoi(val);
3471  } else if (!strcasecmp(param, "autopausebusy")) {
3472  q->autopausebusy = ast_true(val);
3473  } else if (!strcasecmp(param, "autopauseunavail")) {
3474  q->autopauseunavail = ast_true(val);
3475  } else if (!strcasecmp(param, "maxlen")) {
3476  q->maxlen = atoi(val);
3477  if (q->maxlen < 0) {
3478  q->maxlen = 0;
3479  }
3480  } else if (!strcasecmp(param, "servicelevel")) {
3481  q->servicelevel= atoi(val);
3482  } else if (!strcasecmp(param, "strategy")) {
3483  int strategy;
3484 
3485  /* We are a static queue and already have set this, no need to do it again */
3486  if (failunknown) {
3487  return;
3488  }
3489  strategy = strat2int(val);
3490  if (strategy < 0) {
3491  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3492  val, q->name);
3493  strategy = QUEUE_STRATEGY_RINGALL;
3494  }
3495  if (strategy == q->strategy) {
3496  return;
3497  }
3498  if (strategy == QUEUE_STRATEGY_LINEAR) {
3499  ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
3500  return;
3501  }
3502  q->strategy = strategy;
3503  } else if (!strcasecmp(param, "joinempty")) {
3504  parse_empty_options(val, &q->joinempty, 1);
3505  } else if (!strcasecmp(param, "leavewhenempty")) {
3506  parse_empty_options(val, &q->leavewhenempty, 0);
3507  } else if (!strcasecmp(param, "reportholdtime")) {
3508  q->reportholdtime = ast_true(val);
3509  } else if (!strcasecmp(param, "memberdelay")) {
3510  q->memberdelay = atoi(val);
3511  } else if (!strcasecmp(param, "weight")) {
3512  q->weight = atoi(val);
3513  } else if (!strcasecmp(param, "timeoutrestart")) {
3514  q->timeoutrestart = ast_true(val);
3515  } else if (!strcasecmp(param, "defaultrule")) {
3516  ast_string_field_set(q, defaultrule, val);
3517  } else if (!strcasecmp(param, "timeoutpriority")) {
3518  if (!strcasecmp(val, "conf")) {
3519  q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
3520  } else {
3521  q->timeoutpriority = TIMEOUT_PRIORITY_APP;
3522  }
3523  } else if (!strcasecmp(param, "log-restricted-caller-id")) {
3525  } else if (failunknown) {
3526  if (linenum >= 0) {
3527  ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
3528  q->name, param, linenum);
3529  } else {
3530  ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
3531  }
3532  }
3533 }
3534 
3535 
3536 #define QUEUE_PAUSED_DEVSTATE AST_DEVICE_INUSE
3537 #define QUEUE_UNPAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
3538 #define QUEUE_UNKNOWN_PAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
3539 
3540 /*! \internal
3541  * \brief If adding a single new member to a queue, use this function instead of ao2_linking.
3542  * This adds round robin queue position data for a fresh member as well as links it.
3543  * \param queue Which queue the member is being added to
3544  * \param mem Which member is being added to the queue
3545  */
3546 static void member_add_to_queue(struct call_queue *queue, struct member *mem)
3547 {
3548  ao2_lock(queue->members);
3549  mem->queuepos = ao2_container_count(queue->members);
3550  ao2_link(queue->members, mem);
3551  ast_devstate_changed(mem->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
3552  AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
3553  ao2_unlock(queue->members);
3554 }
3555 
3556 /*! \internal
3557  * \brief If removing a single member from a queue, use this function instead of ao2_unlinking.
3558  * This will perform round robin queue position reordering for the remaining members.
3559  * \param queue Which queue the member is being removed from
3560  * \param mem Which member is being removed from the queue
3561  */
3562 static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
3563 {
3564  pending_members_remove(mem);
3565  ao2_lock(queue->members);
3566  ast_devstate_changed(QUEUE_UNKNOWN_PAUSED_DEVSTATE, AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
3567  queue_member_follower_removal(queue, mem);
3568  ao2_unlink(queue->members, mem);
3569  ao2_unlock(queue->members);
3570 }
3571 
3572 /*!
3573  * \brief Find rt member record to update otherwise create one.
3574  *
3575  * Search for member in queue, if found update penalty/paused state,
3576  * if no member exists create one flag it as a RT member and add to queue member list.
3577 */
3578 static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config)
3579 {
3580  struct member *m;
3581  struct ao2_iterator mem_iter;
3582  int penalty = 0;
3583  int paused = 0;
3584  int found = 0;
3585  int wrapuptime = 0;
3586  int ringinuse = q->ringinuse;
3587 
3588  const char *config_val;
3589  const char *interface = ast_variable_retrieve(member_config, category, "interface");
3590  const char *rt_uniqueid = ast_variable_retrieve(member_config, category, "uniqueid");
3591  const char *membername = S_OR(ast_variable_retrieve(member_config, category, "membername"), interface);
3592  const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface);
3593  const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty");
3594  const char *paused_str = ast_variable_retrieve(member_config, category, "paused");
3595  const char *wrapuptime_str = ast_variable_retrieve(member_config, category, "wrapuptime");
3596  const char *reason_paused = ast_variable_retrieve(member_config, category, "reason_paused");
3597 
3598  if (ast_strlen_zero(rt_uniqueid)) {
3599  ast_log(LOG_WARNING, "Realtime field 'uniqueid' is empty for member %s\n",
3600  S_OR(membername, "NULL"));
3601  return;
3602  }
3603 
3604  if (ast_strlen_zero(interface)) {
3605  ast_log(LOG_WARNING, "Realtime field 'interface' is empty for member %s\n",
3606  S_OR(membername, "NULL"));
3607  return;
3608  }
3609 
3610  if (penalty_str) {
3611  penalty = atoi(penalty_str);
3612  if ((penalty < 0) && negative_penalty_invalid) {
3613  return;
3614  } else if (penalty < 0) {
3615  penalty = 0;
3616  }
3617  }
3618 
3619  if (paused_str) {
3620  paused = atoi(paused_str);
3621  if (paused < 0) {
3622  paused = 0;
3623  }
3624  }
3625 
3626  if (wrapuptime_str) {
3627  wrapuptime = atoi(wrapuptime_str);
3628  if (wrapuptime < 0) {
3629  wrapuptime = 0;
3630  }
3631  }
3632 
3633  if ((config_val = ast_variable_retrieve(member_config, category, realtime_ringinuse_field))) {
3634  if (ast_true(config_val)) {
3635  ringinuse = 1;
3636  } else if (ast_false(config_val)) {
3637  ringinuse = 0;
3638  } else {
3639  ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
3640  }
3641  }
3642 
3643  /* Find member by realtime uniqueid and update */
3644  mem_iter = ao2_iterator_init(q->members, 0);
3645  while ((m = ao2_iterator_next(&mem_iter))) {
3646  if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
3647  m->dead = 0; /* Do not delete this one. */
3648  ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
3649  if (paused_str) {
3650  m->paused = paused;
3651  if (paused && m->lastpause == 0) {
3652  time(&m->lastpause); /* XXX: Should this come from realtime? */
3653  }
3654  ast_devstate_changed(m->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
3655  AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, m->interface);
3656  }
3657  if (strcasecmp(state_interface, m->state_interface)) {
3658  ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
3659  }
3660  m->penalty = penalty;
3661  m->ringinuse = ringinuse;
3662  m->wrapuptime = wrapuptime;
3663  if (realtime_reason_paused) {
3664  ast_copy_string(m->reason_paused, S_OR(reason_paused, ""), sizeof(m->reason_paused));
3665  }
3666  found = 1;
3667  ao2_ref(m, -1);
3668  break;
3669  }
3670  ao2_ref(m, -1);
3671  }
3672  ao2_iterator_destroy(&mem_iter);
3673 
3674  /* Create a new member */
3675  if (!found) {
3676  if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse, wrapuptime))) {
3677  m->dead = 0;
3678  m->realtime = 1;
3679  ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
3680  if (!ast_strlen_zero(reason_paused)) {
3681  ast_copy_string(m->reason_paused, reason_paused, sizeof(m->reason_paused));
3682  }
3683  if (!log_membername_as_agent) {
3684  ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
3685  } else {
3686  ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
3687  }
3688  member_add_to_queue(q, m);
3689  ao2_ref(m, -1);
3690  m = NULL;
3691  }
3692  }
3693 }
3694 
3695 /*! \brief Iterate through queue's member list and delete them */
3696 static void free_members(struct call_queue *q, int all)
3697 {
3698  /* Free non-dynamic members */
3699  struct member *cur;
3700  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3701 
3702  while ((cur = ao2_iterator_next(&mem_iter))) {
3703  if (all || !cur->dynamic) {
3704  member_remove_from_queue(q, cur);
3705  }
3706  ao2_ref(cur, -1);
3707  }
3708  ao2_iterator_destroy(&mem_iter);
3709 }
3710 
3711 /*! \brief Free queue's member list then its string fields */
3712 static void destroy_queue(void *obj)
3713 {
3714  struct call_queue *q = obj;
3715  int i;
3716 
3717  free_members(q, 1);
3719  for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3720  if (q->sound_periodicannounce[i]) {
3721  ast_free(q->sound_periodicannounce[i]);
3722  }
3723  }
3724  ao2_ref(q->members, -1);
3725 }
3726 
3727 static struct call_queue *alloc_queue(const char *queuename)
3728 {
3729  struct call_queue *q;
3730 
3731  if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
3732  if (ast_string_field_init(q, 64)) {
3733  queue_t_unref(q, "String field allocation failed");
3734  return NULL;
3735  }
3736  ast_string_field_set(q, name, queuename);
3737  }
3738  return q;
3739 }
3740 
3741 /*!
3742  * \brief Reload a single queue via realtime.
3743  *
3744  * Check for statically defined queue first, check if deleted RT queue,
3745  * check for new RT queue, if queue vars are not defined init them with defaults.
3746  * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
3747  * \retval the queue,
3748  * \retval NULL if it doesn't exist.
3749  * \note Should be called with the "queues" container locked.
3750 */
3751 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
3752 {
3753  struct ast_variable *v;
3754  struct call_queue *q, tmpq = {
3755  .name = queuename,
3756  };
3757  struct member *m;
3758  struct ao2_iterator mem_iter;
3759  char *category = NULL;
3760  const char *tmp_name;
3761  char *tmp;
3762  char tmpbuf[64]; /* Must be longer than the longest queue param name. */
3763 
3764  /* Static queues override realtime. */
3765  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
3766  ao2_lock(q);
3767  if (!q->realtime) {
3768  if (q->dead) {
3769  ao2_unlock(q);
3770  queue_t_unref(q, "Queue is dead; can't return it");
3771  return NULL;
3772  }
3773  ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
3774  ao2_unlock(q);
3775  return q;
3776  }
3777  } else if (!member_config) {
3778  /* Not found in the list, and it's not realtime ... */
3779  return NULL;
3780  }
3781  /* Check if queue is defined in realtime. */
3782  if (!queue_vars) {
3783  /* Delete queue from in-core list if it has been deleted in realtime. */
3784  if (q) {
3785  /*! \note Hmm, can't seem to distinguish a DB failure from a not
3786  found condition... So we might delete an in-core queue
3787  in case of DB failure. */
3788  ast_debug(1, "Queue %s not found in realtime.\n", queuename);
3789 
3790  q->dead = 1;
3791  /* Delete if unused (else will be deleted when last caller leaves). */
3792  queues_t_unlink(queues, q, "Unused; removing from container");
3793  ao2_unlock(q);
3794  queue_t_unref(q, "Queue is dead; can't return it");
3795  }
3796  return NULL;
3797  }
3798 
3799  /* Create a new queue if an in-core entry does not exist yet. */
3800  if (!q) {
3801  struct ast_variable *tmpvar = NULL;
3802  if (!(q = alloc_queue(queuename))) {
3803  return NULL;
3804  }
3805  ao2_lock(q);
3806  clear_queue(q);
3807  q->realtime = 1;
3808  /*Before we initialize the queue, we need to set the strategy, so that linear strategy
3809  * will allocate the members properly
3810  */
3811  for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
3812  if (!strcasecmp(tmpvar->name, "strategy")) {
3813  q->strategy = strat2int(tmpvar->value);
3814  if (q->strategy < 0) {
3815  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3816  tmpvar->value, q->name);
3817  q->strategy = QUEUE_STRATEGY_RINGALL;
3818  }
3819  break;
3820  }
3821  }
3822  /* We traversed all variables and didn't find a strategy */
3823  if (!tmpvar) {
3824  q->strategy = QUEUE_STRATEGY_RINGALL;
3825  }
3826  queues_t_link(queues, q, "Add queue to container");
3827  }
3828  init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
3829 
3830  memset(tmpbuf, 0, sizeof(tmpbuf));
3831  for (v = queue_vars; v; v = v->next) {
3832  /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
3833  if (strchr(v->name, '_')) {
3834  ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
3835  tmp_name = tmpbuf;
3836  tmp = tmpbuf;
3837  while ((tmp = strchr(tmp, '_'))) {
3838  *tmp++ = '-';
3839  }
3840  } else {
3841  tmp_name = v->name;
3842  }
3843 
3844  /* NULL values don't get returned from realtime; blank values should
3845  * still get set. If someone doesn't want a value to be set, they
3846  * should set the realtime column to NULL, not blank. */
3847  queue_set_param(q, tmp_name, v->value, -1, 0);
3848  }
3849 
3850  /* Temporarily set realtime members dead so we can detect deleted ones. */
3851  mem_iter = ao2_iterator_init(q->members, 0);
3852  while ((m = ao2_iterator_next(&mem_iter))) {
3853  if (m->realtime) {
3854  m->dead = 1;
3855  }
3856  ao2_ref(m, -1);
3857  }
3858  ao2_iterator_destroy(&mem_iter);
3859 
3860  while ((category = ast_category_browse(member_config, category))) {
3861  rt_handle_member_record(q, category, member_config);
3862  }
3863 
3864  /* Delete all realtime members that have been deleted in DB. */
3865  mem_iter = ao2_iterator_init(q->members, 0);
3866  while ((m = ao2_iterator_next(&mem_iter))) {
3867  if (m->dead) {
3868  if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
3869  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
3870  } else {
3871  ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
3872  }
3873  member_remove_from_queue(q, m);
3874  }
3875  ao2_ref(m, -1);
3876  }
3877  ao2_iterator_destroy(&mem_iter);
3878 
3879  ao2_unlock(q);
3880 
3881  return q;
3882 }
3883 
3884 /*!
3885  * note */
3886 
3887 /*!
3888  * \internal
3889  * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
3890  * \param queuename - name of the desired queue
3891  *
3892  * \retval the queue
3893  * \retval NULL if it doesn't exist
3894  */
3895 static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
3896 {
3897  struct ast_variable *queue_vars;
3898  struct ast_config *member_config = NULL;
3899  struct call_queue *q = NULL, tmpq = {
3900  .name = queuename,
3901  };
3902  int prev_weight = 0;
3903 
3904  /* Find the queue in the in-core list first. */
3905  q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
3906 
3907  if (!q || q->realtime) {
3908  /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
3909  queue operations while waiting for the DB.
3910 
3911  This will be two separate database transactions, so we might
3912  see queue parameters as they were before another process
3913  changed the queue and member list as it was after the change.
3914  Thus we might see an empty member list when a queue is
3915  deleted. In practise, this is unlikely to cause a problem. */
3916 
3917  queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
3918  if (queue_vars) {
3919  member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
3920  if (!member_config) {
3921  ast_debug(1, "No queue_members defined in config extconfig.conf\n");
3922  member_config = ast_config_new();
3923  }
3924  }
3925  if (q) {
3926  prev_weight = q->weight ? 1 : 0;
3927  queue_t_unref(q, "Need to find realtime queue");
3928  }
3929 
3930  q = find_queue_by_name_rt(queuename, queue_vars, member_config);
3931  ast_config_destroy(member_config);
3932  ast_variables_destroy(queue_vars);
3933 
3934  /* update the use_weight value if the queue's has gained or lost a weight */
3935  if (q) {
3936  if (!q->weight && prev_weight) {
3937  ast_atomic_fetchadd_int(&use_weight, -1);
3938  }
3939  if (q->weight && !prev_weight) {
3940  ast_atomic_fetchadd_int(&use_weight, +1);
3941  }
3942  }
3943  /* Other cases will end up with the proper value for use_weight */
3944  } else {
3945  update_realtime_members(q);
3946  }
3947  return q;
3948 }
3949 
3950 /*!
3951  * \internal
3952  * \brief Load queues and members from realtime.
3953  *
3954  * \param queuename - name of the desired queue to load or empty if need to load all queues
3955 */
3956 static void load_realtime_queues(const char *queuename)
3957 {
3958  struct ast_config *cfg = NULL;
3959  char *category = NULL;
3960  const char *name = NULL;
3961  struct call_queue *q = NULL;
3962 
3963  if (!ast_check_realtime("queues")) {
3964  return;
3965  }
3966 
3967  if (ast_strlen_zero(queuename)) {
3968  if ((cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL))) {
3969  while ((category = ast_category_browse(cfg, category))) {
3970  name = ast_variable_retrieve(cfg, category, "name");
3971  if (!ast_strlen_zero(name) && (q = find_load_queue_rt_friendly(name))) {
3972  queue_unref(q);
3973  }
3974  }
3975  ast_config_destroy(cfg);
3976  }
3977  } else {
3978  if ((q = find_load_queue_rt_friendly(queuename))) {
3979  queue_unref(q);
3980  }
3981  }
3982 }
3983 
3984 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
3985 {
3986  int ret = -1;
3987 
3988  if (ast_strlen_zero(mem->rt_uniqueid)) {
3989  return ret;
3990  }
3991 
3992  if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) >= 0) {
3993  ret = 0;
3994  }
3995 
3996  return ret;
3997 }
3998 
3999 
4000 static void update_realtime_members(struct call_queue *q)
4001 {
4002  struct ast_config *member_config = NULL;
4003  struct member *m;
4004  char *category = NULL;
4005  struct ao2_iterator mem_iter;
4006 
4007  if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
4008  /* This queue doesn't have realtime members. If the queue still has any realtime
4009  * members in memory, they need to be removed.
4010  */
4011  ao2_lock(q);
4012  mem_iter = ao2_iterator_init(q->members, 0);
4013  while ((m = ao2_iterator_next(&mem_iter))) {
4014  if (m->realtime) {
4015  member_remove_from_queue(q, m);
4016  }
4017  ao2_ref(m, -1);
4018  }
4019  ao2_iterator_destroy(&mem_iter);
4020  ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
4021  ao2_unlock(q);
4022  return;
4023  }
4024 
4025  ao2_lock(q);
4026 
4027  /* Temporarily set realtime members dead so we can detect deleted ones.*/
4028  mem_iter = ao2_iterator_init(q->members, 0);
4029  while ((m = ao2_iterator_next(&mem_iter))) {
4030  if (m->realtime) {
4031  m->dead = 1;
4032  }
4033  ao2_ref(m, -1);
4034  }
4035  ao2_iterator_destroy(&mem_iter);
4036 
4037  while ((category = ast_category_browse(member_config, category))) {
4038  rt_handle_member_record(q, category, member_config);
4039  }
4040 
4041  /* Delete all realtime members that have been deleted in DB. */
4042  mem_iter = ao2_iterator_init(q->members, 0);
4043  while ((m = ao2_iterator_next(&mem_iter))) {
4044  if (m->dead) {
4045  if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
4046  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
4047  } else {
4048  ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
4049  }
4050  member_remove_from_queue(q, m);
4051  }
4052  ao2_ref(m, -1);
4053  }
4054  ao2_iterator_destroy(&mem_iter);
4055  ao2_unlock(q);
4056  ast_config_destroy(member_config);
4057 }
4058 
4059 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
4060 {
4061  struct call_queue *q;
4062  struct queue_ent *cur, *prev = NULL;
4063  int res = -1;
4064  int pos = 0;
4065  int inserted = 0;
4066 
4067  if (!(q = find_load_queue_rt_friendly(queuename))) {
4068  return res;
4069  }
4070  ao2_lock(q);
4071 
4072  /* This is our one */
4073  if (q->joinempty) {
4074  int status = 0;
4075  if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, qe->raise_penalty, q->joinempty, 0))) {
4076  *reason = QUEUE_JOINEMPTY;
4077  ao2_unlock(q);
4078  queue_t_unref(q, "Done with realtime queue");
4079  return res;
4080  }
4081  }
4082  if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
4083  *reason = QUEUE_FULL;
4084  } else if (*reason == QUEUE_UNKNOWN) {
4085  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4086 
4087  /* There's space for us, put us at the right position inside
4088  * the queue.
4089  * Take into account the priority of the calling user */
4090  inserted = 0;
4091  prev = NULL;
4092  cur = q->head;
4093  while (cur) {
4094  /* We have higher priority than the current user, enter
4095  * before him, after all the other users with priority
4096  * higher or equal to our priority. */
4097  if ((!inserted) && (qe->prio > cur->prio)) {
4098  insert_entry(q, prev, qe, &pos);
4099  inserted = 1;
4100  }
4101  /* <= is necessary for the position comparison because it may not be possible to enter
4102  * at our desired position since higher-priority callers may have taken the position we want
4103  */
4104  if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
4105  insert_entry(q, prev, qe, &pos);
4106  inserted = 1;
4107  /*pos is incremented inside insert_entry, so don't need to add 1 here*/
4108  if (position < pos) {
4109  ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
4110  }
4111  }
4112  cur->pos = ++pos;
4113  prev = cur;
4114  cur = cur->next;
4115  }
4116  /* No luck, join at the end of the queue */
4117  if (!inserted) {
4118  insert_entry(q, prev, qe, &pos);
4119  }
4120  ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
4121  ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
4122  ast_copy_string(qe->context, q->context, sizeof(qe->context));
4123  q->count++;
4124  if (q->count == 1) {
4126  }
4127 
4128  res = 0;
4129 
4130  blob = ast_json_pack("{s: s, s: i, s: i}",
4131  "Queue", q->name,
4132  "Position", qe->pos,
4133  "Count", q->count);
4134  ast_channel_publish_cached_blob(qe->chan, queue_caller_join_type(), blob);
4135  ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
4136  }
4137  ao2_unlock(q);
4138  queue_t_unref(q, "Done with realtime queue");
4139 
4140  return res;
4141 }
4142 
4143 static int play_file(struct ast_channel *chan, const char *filename)
4144 {
4145  int res;
4146 
4147  if (ast_strlen_zero(filename)) {
4148  return 0;
4149  }
4150 
4151  if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
4152  return 0;
4153  }
4154 
4155  ast_stopstream(chan);
4156 
4157  res = ast_streamfile(chan, filename, ast_channel_language(chan));
4158  if (!res) {
4159  res = ast_waitstream(chan, AST_DIGIT_ANY);
4160  }
4161 
4162  ast_stopstream(chan);
4163 
4164  return res;
4165 }
4166 
4167 /*!
4168  * \brief Check for valid exit from queue via goto
4169  * \retval 0 if failure
4170  * \retval 1 if successful
4171 */
4172 static int valid_exit(struct queue_ent *qe, char digit)
4173 {
4174  int digitlen = strlen(qe->digits);
4175 
4176  /* Prevent possible buffer overflow */
4177  if (digitlen < sizeof(qe->digits) - 2) {
4178  qe->digits[digitlen] = digit;
4179  qe->digits[digitlen + 1] = '\0';
4180  } else {
4181  qe->digits[0] = '\0';
4182  return 0;
4183  }
4184 
4185  /* If there's no context to goto, short-circuit */
4186  if (ast_strlen_zero(qe->context)) {
4187  return 0;
4188  }
4189 
4190  /* If the extension is bad, then reset the digits to blank */
4191  if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
4192  S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, NULL))) {
4193  qe->digits[0] = '\0';
4194  return 0;
4195  }
4196 
4197  /* We have an exact match */
4198  if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
4199  qe->valid_digits = 1;
4200  /* Return 1 on a successful goto */
4201  return 1;
4202  }
4203 
4204  return 0;
4205 }
4206 
4207 static int say_position(struct queue_ent *qe, int ringing)
4208 {
4209  int res = 0, say_thanks = 0;
4210  long avgholdmins, avgholdsecs;
4211  time_t now;
4212 
4213  /* Let minannouncefrequency seconds pass between the start of each position announcement */
4214  time(&now);
4215  if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
4216  return 0;
4217  }
4218 
4219  /* If either our position has changed, or we are over the freq timer, say position */
4220  if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
4221  return 0;
4222  }
4223 
4224  /* Only announce if the caller's queue position has improved since last time */
4225  if (qe->parent->announceposition_only_up && qe->last_pos_said <= qe->pos) {
4226  return 0;
4227  }
4228 
4229  if (ringing) {
4230  ast_indicate(qe->chan,-1);
4231  } else {
4232  ast_moh_stop(qe->chan);
4233  }
4234 
4235  if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
4236  qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
4237  (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
4238  qe->pos <= qe->parent->announcepositionlimit)) {
4239  say_thanks = 1;
4240  /* Say we're next, if we are */
4241  if (qe->pos == 1) {
4242  res = play_file(qe->chan, qe->parent->sound_next);
4243  if (!res) {
4244  goto posout;
4245  }
4246  /* Say there are more than N callers */
4247  } else if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit) {
4248  res = (
4249  play_file(qe->chan, qe->parent->queue_quantity1) ||
4250  ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY,
4251  ast_channel_language(qe->chan), NULL) || /* Needs gender */
4252  play_file(qe->chan, qe->parent->queue_quantity2));
4253  /* Say there are currently N callers waiting */
4254  } else {
4255  res = (
4256  play_file(qe->chan, qe->parent->sound_thereare) ||
4257  ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY,
4258  ast_channel_language(qe->chan), "n") || /* Needs gender */
4259  play_file(qe->chan, qe->parent->sound_calls));
4260  }
4261  if (res) {
4262  goto playout;
4263  }
4264  }
4265  /* Round hold time to nearest minute */
4266  avgholdmins = labs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
4267 
4268  /* If they have specified a rounding then round the seconds as well */
4269  if (qe->parent->roundingseconds) {
4270  avgholdsecs = (labs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
4271  avgholdsecs *= qe->parent->roundingseconds;
4272  } else {
4273  avgholdsecs = 0;
4274  }
4275 
4276  ast_verb(3, "Hold time for %s is %ld minute(s) %ld seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
4277 
4278  /* If the hold time is >1 min, if it's enabled, and if it's not
4279  supposed to be only once and we have already said it, say it */
4280  if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
4281  ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
4282  !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
4283  say_thanks = 1;
4284  res = play_file(qe->chan, qe->parent->sound_holdtime);
4285  if (res) {
4286  goto playout;
4287  }
4288 
4289  if (avgholdmins >= 1) {
4290  res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), "n");
4291  if (res) {
4292  goto playout;
4293  }
4294 
4295  if (avgholdmins == 1) {
4296  res = play_file(qe->chan, qe->parent->sound_minute);
4297  if (res) {
4298  goto playout;
4299  }
4300  } else {
4301  res = play_file(qe->chan, qe->parent->sound_minutes);
4302  if (res) {
4303  goto playout;
4304  }
4305  }
4306  }
4307  if (avgholdsecs >= 1) {
4308  res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), "n");
4309  if (res) {
4310  goto playout;
4311  }
4312 
4313  res = play_file(qe->chan, qe->parent->sound_seconds);
4314  if (res) {
4315  goto playout;
4316  }
4317  }
4318  }
4319 
4320 posout:
4321  if (qe->parent->announceposition) {
4322  ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
4323  ast_channel_name(qe->chan), qe->parent->name, qe->pos);
4324  }
4325  if (say_thanks) {
4326  res = play_file(qe->chan, qe->parent->sound_thanks);
4327  }
4328 playout:
4329 
4330  if ((res > 0 && !valid_exit(qe, res))) {
4331  res = 0;
4332  }
4333 
4334  /* Set our last_pos indicators */
4335  qe->last_pos = now;
4336  qe->last_pos_said = qe->pos;
4337 
4338  /* Don't restart music on hold if we're about to exit the caller from the queue */
4339  if (!res) {
4340  if (ringing) {
4342  } else {
4343  ast_moh_start(qe->chan, qe->moh, NULL);
4344  }
4345  }
4346  return res;
4347 }
4348 
4349 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
4350 {
4351  int oldvalue;
4352 
4353  /* Calculate holdtime using an exponential average */
4354  /* Thanks to SRT for this contribution */
4355  /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
4356 
4357  ao2_lock(qe->parent);
4358  if ((qe->parent->callscompleted + qe->parent->callsabandoned) == 0) {
4359  qe->parent->holdtime = newholdtime;
4360  } else {
4361  oldvalue = qe->parent->holdtime;
4362  qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
4363  }
4364  ao2_unlock(qe->parent);
4365 }
4366 
4367 /*! \brief Caller leaving queue.
4368  *
4369  * Search the queue to find the leaving client, if found remove from queue
4370  * create manager event, move others up the queue.
4371 */
4372 static void leave_queue(struct queue_ent *qe)
4373 {
4374  struct call_queue *q;
4375  struct queue_ent *current, *prev = NULL;
4376  struct penalty_rule *pr_iter;
4377  int pos = 0;
4378 
4379  if (!(q = qe->parent)) {
4380  return;
4381  }
4382  queue_t_ref(q, "Copy queue pointer from queue entry");
4383  ao2_lock(q);
4384 
4385  prev = NULL;
4386  for (current = q->head; current; current = current->next) {
4387  if (current == qe) {
4388  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4389  char posstr[20];
4390  q->count--;
4391  if (!q->count) {
4393  }
4394 
4395  blob = ast_json_pack("{s: s, s: i, s: i}",
4396  "Queue", q->name,
4397  "Position", qe->pos,
4398  "Count", q->count);
4399  ast_channel_publish_cached_blob(qe->chan, queue_caller_leave_type(), blob);
4400  ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
4401  /* Take us out of the queue */
4402  if (prev) {
4403  prev->next = current->next;
4404  } else {
4405  q->head = current->next;
4406  }
4407  /* Free penalty rules */
4408  while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
4409  ast_free(pr_iter);
4410  }
4411  qe->pr = NULL;
4412  snprintf(posstr, sizeof(posstr), "%d", qe->pos);
4413  pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
4414  } else {
4415  /* Renumber the people after us in the queue based on a new count */
4416  current->pos = ++pos;
4417  prev = current;
4418  }
4419  }
4420  ao2_unlock(q);
4421 
4422  /*If the queue is a realtime queue, check to see if it's still defined in real time*/
4423  if (q->realtime) {
4424  struct ast_variable *var;
4425  if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
4426  q->dead = 1;
4427  } else {
4428  ast_variables_destroy(var);
4429  }
4430  }
4431 
4432  if (q->dead) {
4433  /* It's dead and nobody is in it, so kill it */
4434  queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
4435  }
4436  /* unref the explicit ref earlier in the function */
4437  queue_t_unref(q, "Expire copied reference");
4438 }
4439 
4440 /*!
4441  * \internal
4442  * \brief Destroy the given callattempt structure and free it.
4443  * \since 1.8
4444  *
4445  * \param doomed callattempt structure to destroy.
4446  */
4447 static void callattempt_free(struct callattempt *doomed)
4448 {
4449  if (doomed->member) {
4450  ao2_ref(doomed->member, -1);
4451  }
4453  ast_free(doomed->orig_chan_name);
4454  ast_free(doomed);
4455 }
4456 
4457 static void publish_dial_end_event(struct ast_channel *in, struct callattempt *outgoing, struct ast_channel *exception, const char *status)
4458 {
4459  struct callattempt *cur;
4460 
4461  for (cur = outgoing; cur; cur = cur->q_next) {
4462  if (cur->chan && cur->chan != exception) {
4463  ast_channel_publish_dial(in, cur->chan, NULL, status);
4464  }
4465  }
4466 }
4467 
4468 /*! \brief Hang up a list of outgoing calls */
4469 static void hangupcalls(struct queue_ent *qe, struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
4470 {
4471  struct callattempt *oo;
4472 
4473  while (outgoing) {
4474  /* If someone else answered the call we should indicate this in the CANCEL */
4475  /* Hangup any existing lines we have open */
4476  if (outgoing->chan && (outgoing->chan != exception)) {
4477  if (exception || cancel_answered_elsewhere) {
4478  ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
4479  }
4480  ast_channel_publish_dial(qe->chan, outgoing->chan, outgoing->interface, "CANCEL");
4481 
4482  /* When dialing channels it is possible that they may not ever
4483  * leave the not in use state (Local channels in particular) by
4484  * the time we cancel them. If this occurs but we know they were
4485  * dialed we explicitly remove them from the pending members
4486  * container so that subsequent call attempts occur.
4487  */
4488  if (outgoing->member->status == AST_DEVICE_NOT_INUSE) {
4489  pending_members_remove(outgoing->member);
4490  }
4491 
4492  ast_hangup(outgoing->chan);
4493  }
4494  oo = outgoing;
4495  outgoing = outgoing->q_next;
4496  ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
4497  callattempt_free(oo);
4498  }
4499 }
4500 
4501 /*!
4502  * \brief Get the number of members available to accept a call.
4503  *
4504  * \note The queue passed in should be locked prior to this function call
4505  *
4506  * \param[in] q The queue for which we are counting the number of available members
4507  * \return Return the number of available members in queue q
4508  */
4509 static int num_available_members(struct call_queue *q)
4510 {
4511  struct member *mem;
4512  int avl = 0;
4513  struct ao2_iterator mem_iter;
4514 
4515  mem_iter = ao2_iterator_init(q->members, 0);
4516  while ((mem = ao2_iterator_next(&mem_iter))) {
4517 
4518  avl += is_member_available(q, mem);
4519  ao2_ref(mem, -1);
4520 
4521  /* If autofill is not enabled or if the queue's strategy is ringall, then
4522  * we really don't care about the number of available members so much as we
4523  * do that there is at least one available.
4524  *
4525  * In fact, we purposely will return from this function stating that only
4526  * one member is available if either of those conditions hold. That way,
4527  * functions which determine what action to take based on the number of available
4528  * members will operate properly. The reasoning is that even if multiple
4529  * members are available, only the head caller can actually be serviced.
4530  */
4531  if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
4532  break;
4533  }
4534  }
4535  ao2_iterator_destroy(&mem_iter);
4536 
4537  return avl;
4538 }
4539 
4540 /* traverse all defined queues which have calls waiting and contain this member
4541  return 0 if no other queue has precedence (higher weight) or 1 if found */
4542 static int compare_weight(struct call_queue *rq, struct member *member)
4543 {
4544  struct call_queue *q;
4545  struct member *mem;
4546  int found = 0;
4547  struct ao2_iterator queue_iter;
4548 
4549  queue_iter = ao2_iterator_init(queues, 0);
4550  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4551  if (q == rq) { /* don't check myself, could deadlock */
4552  queue_t_unref(q, "Done with iterator");
4553  continue;
4554  }
4555  ao2_lock(q);
4556  if (q->count && q->members) {
4557  if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
4558  ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
4559  if (q->weight > rq->weight && q->count >= num_available_members(q)) {
4560  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);
4561  found = 1;
4562  }
4563  ao2_ref(mem, -1);
4564  }
4565  }
4566  ao2_unlock(q);
4567  queue_t_unref(q, "Done with iterator");
4568  if (found) {
4569  break;
4570  }
4571  }
4572  ao2_iterator_destroy(&queue_iter);
4573  return found;
4574 }
4575 
4576 static int is_longest_waiting_caller(struct queue_ent *caller, struct member *member)
4577 {
4578  struct call_queue *q;
4579  struct member *mem;
4580  int is_longest_waiting = 1;
4581  struct ao2_iterator queue_iter;
4582  struct queue_ent *ch;
4583 
4584  queue_iter = ao2_iterator_init(queues, 0);
4585  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4586  if (q == caller->parent) { /* don't check myself, could deadlock */
4587  queue_t_unref(q, "Done with iterator");
4588  continue;
4589  }
4590  ao2_lock(q);
4591  /*
4592  * If the other queue has equal weight, see if we should let that handle
4593  * their call first. If weights are not equal, compare_weights will step in.
4594  */
4595  if (q->weight == caller->parent->weight && q->count && q->members) {
4596  if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
4597  ast_debug(2, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
4598 
4599  /* Does this queue have a caller that's been waiting longer? */
4600  ch = q->head;
4601  while (ch) {
4602  /* If ch->pending, the other call (which may be waiting for a longer period of time),
4603  * is already ringing at another agent. Ignore such callers; otherwise, all agents
4604  * will be unused until the first caller is picked up.
4605  */
4606  if (ch->start < caller->start && !ch->pending) {
4607  ast_debug(1, "Queue %s has a call at position %i that's been waiting longer (%li vs %li)\n",
4608  q->name, ch->pos, ch->start, caller->start);
4609  is_longest_waiting = 0;
4610  break;
4611  }
4612  ch = ch->next;
4613  }
4614  }
4615  }
4616  ao2_unlock(q);
4617  queue_t_unref(q, "Done with iterator");
4618  if (!is_longest_waiting) {
4619  break;
4620  }
4621  }
4622  ao2_iterator_destroy(&queue_iter);
4623  return is_longest_waiting;
4624 }
4625 
4626 /*! \brief common hangup actions */
4627 static void do_hang(struct callattempt *o)
4628 {
4629  o->stillgoing = 0;
4630  ast_hangup(o->chan);
4631  pending_members_remove(o->member);
4632  o->chan = NULL;
4633 }
4634 
4635 /*!
4636  * \internal
4637  * \brief Check if the member status is available.
4638  *
4639  * \param status Member status to check if available.
4640  *
4641  * \retval non-zero if the member status is available.
4642  */
4643 static int member_status_available(int status)
4644 {
4645  return status == AST_DEVICE_NOT_INUSE || status == AST_DEVICE_UNKNOWN;
4646 }
4647 
4648 /*!
4649  * \internal
4650  * \brief Determine if can ring a queue entry.
4651  *
4652  * \param qe Queue entry to check.
4653  * \param call Member call attempt.
4654  *
4655  * \retval non-zero if an entry can be called.
4656  */
4657 static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
4658 {
4659  struct member *memberp = call->member;
4660  int wrapuptime;
4661 
4662  if (memberp->paused) {
4663  ast_debug(1, "%s paused, can't receive call\n", call->interface);
4664  return 0;
4665  }
4666 
4667  if (!memberp->ringinuse && !member_status_available(memberp->status)) {
4668  ast_debug(1, "%s not available, can't receive call\n", call->interface);
4669  return 0;
4670  }
4671 
4672  if (memberp->lastqueue) {
4673  wrapuptime = get_wrapuptime(memberp->lastqueue, memberp);
4674  } else {
4675  wrapuptime = get_wrapuptime(qe->parent, memberp);
4676  }
4677  if (wrapuptime && (time(NULL) - memberp->lastcall) < wrapuptime) {
4678  ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
4679  (memberp->lastqueue ? memberp->lastqueue->name : qe->parent->name),
4680  call->interface);
4681  return 0;
4682  }
4683 
4684  if (use_weight && compare_weight(qe->parent, memberp)) {
4685  ast_debug(1, "Priority queue delaying call to %s:%s\n",
4686  qe->parent->name, call->interface);
4687  return 0;
4688  }
4689 
4690  if (force_longest_waiting_caller && !is_longest_waiting_caller(qe, memberp)) {
4691  ast_debug(1, "Another caller was waiting longer; delaying call to %s:%s\n",
4692  qe->parent->name, call->interface);
4693  return 0;
4694  }
4695 
4696  if (!memberp->ringinuse) {
4697  struct member *mem;
4698 
4699  ao2_lock(pending_members);
4700 
4701  mem = ao2_find(pending_members, memberp,
4703  if (mem) {
4704  /*
4705  * If found that means this member is currently being attempted
4706  * from another calling thread, so stop trying from this thread
4707  */
4708  ast_debug(1, "%s has another call trying, can't receive call\n",
4709  call->interface);
4710  ao2_ref(mem, -1);
4711  ao2_unlock(pending_members);
4712  return 0;
4713  }
4714 
4715  /*
4716  * If not found add it to the container so another queue
4717  * won't attempt to call this member at the same time.
4718  */
4719  ast_debug(3, "Add %s to pending_members\n", memberp->membername);
4720  ao2_link(pending_members, memberp);
4721  ao2_unlock(pending_members);
4722 
4723  /*
4724  * The queue member is available. Get current status to be sure
4725  * because the device state and extension state callbacks may
4726  * not have updated the status yet.
4727  */
4728  if (!member_status_available(get_queue_member_status(memberp))) {
4729  ast_debug(1, "%s actually not available, can't receive call\n",
4730  call->interface);
4731  pending_members_remove(memberp);
4732  return 0;
4733  }
4734  }
4735 
4736  return 1;
4737 }
4738 
4739 /*!
4740  * \brief Part 2 of ring_one
4741  *
4742  * Does error checking before attempting to request a channel and call a member.
4743  * This function is only called from ring_one().
4744  * Failure can occur if:
4745  * - Agent on call
4746  * - Agent is paused
4747  * - Wrapup time not expired
4748  * - Priority by another queue
4749  *
4750  * \retval 1 on success to reach a free agent
4751  * \retval 0 on failure to get agent.
4752  */
4753 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
4754 {
4755  int res;
4756  int status;
4757  char tech[256];
4758  char *location;
4759  struct ast_format_cap *nativeformats;
4760  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
4761 
4762  /* on entry here, we know that tmp->chan == NULL */
4763  if (!can_ring_entry(qe, tmp)) {
4764  tmp->stillgoing = 0;
4765  ++*busies;
4766  return 0;
4767  }
4768 
4769  ast_copy_string(tech, tmp->interface, sizeof(tech));
4770  if ((location = strchr(tech, '/'))) {
4771  *location++ = '\0';
4772  } else {
4773  location = "";
4774  }
4775 
4776  ast_channel_lock(qe->chan);
4777  nativeformats = ao2_bump(ast_channel_nativeformats(qe->chan));
4778  ast_channel_unlock(qe->chan);
4779 
4780  /* Request the peer */
4781  tmp->chan = ast_request(tech, nativeformats, NULL, qe->chan, location, &status);
4782  ao2_cleanup(nativeformats);
4783  if (!tmp->chan) { /* If we can't, just go on to the next call */
4784  ao2_lock(qe->parent);
4785  qe->parent->rrpos++;
4786  qe->linpos++;
4787  ao2_unlock(qe->parent);
4788 
4789  pending_members_remove(tmp->member);
4790 
4791  publish_dial_end_event(qe->chan, tmp, NULL, "BUSY");
4792  tmp->stillgoing = 0;
4793  ++*busies;
4794  return 0;
4795  }
4796 
4797  ast_channel_lock_both(tmp->chan, qe->chan);
4798 
4801  if (qe->cancel_answered_elsewhere) {
4802  ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
4803  }
4804  ast_channel_appl_set(tmp->chan, "AppQueue");
4805  ast_channel_data_set(tmp->chan, "(Outgoing Line)");
4806  memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
4807 
4808  /* If the new channel has no callerid, try to guess what it should be */
4809  if (!ast_channel_caller(tmp->chan)->id.number.valid) {
4810  if (ast_channel_connected(qe->chan)->id.number.valid) {
4811  struct ast_party_caller caller;
4812 
4813  ast_party_caller_set_init(&caller, ast_channel_caller(tmp->chan));
4814  caller.id = ast_channel_connected(qe->chan)->id;
4815  caller.ani = ast_channel_connected(qe->chan)->ani;
4816  ast_channel_set_caller_event(tmp->chan, &caller, NULL);
4817  } else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
4818  ast_set_callerid(tmp->chan, ast_channel_dialed(qe->chan)->number.str, NULL, NULL);
4819  } else if (!ast_strlen_zero(ast_channel_exten(qe->chan))) {
4820  ast_set_callerid(tmp->chan, ast_channel_exten(qe->chan), NULL, NULL);
4821  }
4822  tmp->dial_callerid_absent = 1;
4823  }
4824 
4825  ast_party_redirecting_copy(ast_channel_redirecting(tmp->chan), ast_channel_redirecting(qe->chan));
4826 
4827  ast_channel_dialed(tmp->chan)->transit_network_select = ast_channel_dialed(qe->chan)->transit_network_select;
4828 
4829  ast_connected_line_copy_from_caller(ast_channel_connected(tmp->chan), ast_channel_caller(qe->chan));
4830 
4831  /* Inherit specially named variables from parent channel */
4832  ast_channel_inherit_variables(qe->chan, tmp->chan);
4833  ast_channel_datastore_inherit(qe->chan, tmp->chan);
4834  ast_max_forwards_decrement(tmp->chan);
4835 
4836  /* Presense of ADSI CPE on outgoing channel follows ours */
4837  ast_channel_adsicpe_set(tmp->chan, ast_channel_adsicpe(qe->chan));
4838 
4839  /* Inherit context and extension */
4840  ast_channel_dialcontext_set(tmp->chan, ast_channel_context(qe->chan));
4841  ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));
4842 
4843  /* Save the original channel name to detect call pickup masquerading in. */
4844  tmp->orig_chan_name = ast_strdup(ast_channel_name(tmp->chan));
4845 
4846  ast_channel_unlock(tmp->chan);
4847  ast_channel_unlock(qe->chan);
4848 
4849  /* location is tmp->interface where tech/ has been stripped, so it follow the same syntax as DIALEDPEERNUMBER in app_dial.c */
4850  pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", strlen(location) ? location : tmp->interface);
4851 
4852  /* PREDIAL: Run gosub on the callee's channel */
4853  if (qe->predial_callee) {
4854  ast_pre_call(tmp->chan, qe->predial_callee);
4855  }
4856 
4857  /* Place the call, but don't wait on the answer */
4858  if ((res = ast_call(tmp->chan, location, 0))) {
4859  /* Again, keep going even if there's an error */
4860  ast_verb(3, "Couldn't call %s\n", tmp->interface);
4861  do_hang(tmp);
4862  ++*busies;
4863  return 0;
4864  }
4865 
4866  ast_channel_lock_both(tmp->chan, qe->chan);
4867 
4868  blob = ast_json_pack("{s: s, s: s, s: s}",
4869  "Queue", qe->parent->name,
4870  "Interface", tmp->interface,
4871  "MemberName", tmp->member->membername);
4872  queue_publish_multi_channel_blob(qe->chan, tmp->chan, queue_agent_called_type(), blob);
4873 
4874  ast_channel_publish_dial(qe->chan, tmp->chan, tmp->interface, NULL);
4875 
4876  ast_channel_unlock(tmp->chan);
4877  ast_channel_unlock(qe->chan);
4878 
4879  ast_verb(3, "Called %s\n", tmp->interface);
4880 
4881  return 1;
4882 }
4883 
4884 /*! \brief find the entry with the best metric, or NULL */
4885 static struct callattempt *find_best(struct callattempt *outgoing)
4886 {
4887  struct callattempt *best = NULL, *cur;
4888 
4889  for (cur = outgoing; cur; cur = cur->q_next) {
4890  if (cur->stillgoing && /* Not already done */
4891  !cur->chan && /* Isn't already going */
4892  (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
4893  best = cur;
4894  }
4895  }
4896 
4897  return best;
4898 }
4899 
4900 /*!
4901  * \brief Place a call to a queue member.
4902  *
4903  * Once metrics have been calculated for each member, this function is used
4904  * to place a call to the appropriate member (or members). The low-level
4905  * channel-handling and error detection is handled in ring_entry
4906  *
4907  * \retval 1 if a member was called successfully
4908  * \retval 0 otherwise
4909  */
4910 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
4911 {
4912  int ret = 0;
4913  struct callattempt *cur;
4914 
4915  if (qe->predial_callee) {
4917  for (cur = outgoing; cur; cur = cur->q_next) {
4918  if (cur->stillgoing && cur->chan) {
4919  ast_autoservice_start(cur->chan);
4920  }
4921  }
4922  }
4923 
4924  while (ret == 0) {
4925  struct callattempt *best = find_best(outgoing);
4926  if (!best) {
4927  ast_debug(1, "Nobody left to try ringing in queue\n");
4928  break;
4929  }
4930  if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
4931  /* Ring everyone who shares this best metric (for ringall) */
4932  for (cur = outgoing; cur; cur = cur->q_next) {
4933  if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
4934  ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
4935  ret |= ring_entry(qe, cur, busies);
4936  if (qe->predial_callee && cur->chan) {
4937  ast_autoservice_start(cur->chan);
4938  }
4939  }
4940  }
4941  } else {
4942  /* Ring just the best channel */
4943  ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
4944  ret = ring_entry(qe, best, busies);
4945  if (qe->predial_callee && best->chan) {
4946  ast_autoservice_start(best->chan);
4947  }
4948  }
4949 
4950  /* If we have timed out, break out */
4951  if (qe->expire && (time(NULL) >= qe->expire)) {
4952  ast_debug(1, "Queue timed out while ringing members.\n");
4953  ret = 0;
4954  break;
4955  }
4956  }
4957  if (qe->predial_callee) {
4958  for (cur = outgoing; cur; cur = cur->q_next) {
4959  if (cur->stillgoing && cur->chan) {
4960  ast_autoservice_stop(cur->chan);
4961  }
4962  }
4964  }
4965 
4966  return ret;
4967 }
4968 
4969 /*! \brief Search for best metric and add to Round Robbin queue */
4970 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
4971 {
4972  struct callattempt *best = find_best(outgoing);
4973 
4974  if (best) {
4975  /* Ring just the best channel */
4976  ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
4977  qe->parent->rrpos = best->metric % 1000;
4978  } else {
4979  /* Just increment rrpos */
4980  if (qe->parent->wrapped) {
4981  /* No more channels, start over */
4982  qe->parent->rrpos = 0;
4983  } else {
4984  /* Prioritize next entry */
4985  qe->parent->rrpos++;
4986  }
4987  }
4988  qe->parent->wrapped = 0;
4989 
4990  return 0;
4991 }
4992 
4993 /*! \brief Search for best metric and add to Linear queue */
4994 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
4995 {
4996  struct callattempt *best = find_best(outgoing);
4997 
4998  if (best) {
4999  /* Ring just the best channel */
5000  ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
5001  qe->linpos = best->metric % 1000;
5002  } else {
5003  /* Just increment rrpos */
5004  if (qe->linwrapped) {
5005  /* No more channels, start over */
5006  qe->linpos = 0;
5007  } else {
5008  /* Prioritize next entry */
5009  qe->linpos++;
5010  }
5011  }
5012  qe->linwrapped = 0;
5013 
5014  return 0;
5015 }
5016 
5017 /*! \brief Playback announcement to queued members if period has elapsed */
5018 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
5019 {
5020  int res = 0;
5021  time_t now;
5022 
5023  /* Get the current time */
5024  time(&now);
5025 
5026  /* Check to see if it is time to announce */
5028  return 0;
5029  }
5030 
5031  /* Stop the music on hold so we can play our own file */
5032  if (ringing) {
5033  ast_indicate(qe->chan,-1);
5034  } else {
5035  ast_moh_stop(qe->chan);
5036  }
5037 
5038  ast_verb(3, "Playing periodic announcement\n");
5039 
5041  qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
5042  } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
5045  }
5046 
5047  /* play the announcement */
5049 
5050  if (res > 0 && !valid_exit(qe, res)) {
5051  res = 0;
5052  }
5053 
5054  /* Resume Music on Hold if the caller is going to stay in the queue */
5055  if (!res) {
5056  if (ringing) {
5058  } else {
5059  ast_moh_start(qe->chan, qe->moh, NULL);
5060  }
5061  }
5062 
5063  /* update last_periodic_announce_time */
5064  if (qe->parent->relativeperiodicannounce) {
5065  time(&qe->last_periodic_announce_time);
5066  } else {
5067  qe->last_periodic_announce_time = now;
5068  }
5069 
5070  /* Update the current periodic announcement to the next announcement */
5071  if (!qe->parent->randomperiodicannounce) {
5073  }
5074 
5075  return res;
5076 }
5077 
5078 /*! \brief Record that a caller gave up on waiting in queue */
5079 static void record_abandoned(struct queue_ent *qe)
5080 {
5081  int callabandonedinsl = 0;
5082  time_t now;
5083 
5084  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
5085 
5086  pbx_builtin_setvar_helper(qe->chan, "ABANDONED", "TRUE");
5087 
5088  set_queue_variables(qe->parent, qe->chan);
5089  ao2_lock(qe->parent);
5090  blob = ast_json_pack("{s: s, s: i, s: i, s: i}",
5091  "Queue", qe->parent->name,
5092  "Position", qe->pos,
5093  "OriginalPosition", qe->opos,
5094  "HoldTime", (int)(time(NULL) - qe->start));
5095 
5096 
5097  time(&now);
5098  callabandonedinsl = ((now - qe->start) <= qe->parent->servicelevel);
5099  if (callabandonedinsl) {
5100  qe->parent->callsabandonedinsl++;
5101  }
5102 
5103  qe->parent->callsabandoned++;
5104  ao2_unlock(qe->parent);
5105 
5106  ast_channel_publish_cached_blob(qe->chan, queue_caller_abandon_type(), blob);
5107 }
5108 
5109 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
5110 static void rna(int rnatime, struct queue_ent *qe, struct ast_channel *peer, char *interface, char *membername, int autopause)
5111 {
5112  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
5113 
5114  ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
5115 
5116  /* Stop ringing, and resume MOH if specified */
5117  if (qe->ring_when_ringing) {
5118  ast_indicate(qe->chan, -1);
5119  ast_moh_start(qe->chan, qe->moh, NULL);
5120  }
5121 
5122  blob = ast_json_pack("{s: s, s: s, s: s, s: i}",
5123  "Queue", qe->parent->name,
5124  "Interface", interface,
5125  "MemberName", membername,
5126  "RingTime", rnatime);
5127  queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_ringnoanswer_type(), blob);
5128 
5129  ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
5130  if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
5131  if (qe->parent->autopausedelay > 0) {
5132  struct member *mem;
5133  ao2_lock(qe->parent);
5134  if ((mem = interface_exists(qe->parent, interface))) {
5135  time_t idletime = time(&idletime)-mem->lastcall;
5136  if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
5137  ao2_unlock(qe->parent);
5138  ao2_ref(mem, -1);
5139  return;
5140  }
5141  ao2_ref(mem, -1);
5142  }
5143  ao2_unlock(qe->parent);
5144  }
5145  if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
5146  if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
5147  ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
5148  interface, qe->parent->name);
5149  } else {
5150  ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
5151  }
5152  } else {
5153  /* If queue autopause is mode all, just don't send any queue to stop.
5154  * the function will stop in all queues */
5155  if (!set_member_paused("", interface, "Auto-Pause", 1)) {
5156  ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
5157  interface, qe->parent->name);
5158  } else {
5159  ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
5160  }
5161  }
5162  }
5163  return;
5164 }
5165 
5166 /*!
5167  * \internal
5168  * \brief Update connected line on chan from peer.
5169  * \since 13.6.0
5170  *
5171  * \param chan Channel to get connected line updated.
5172  * \param peer Channel providing connected line information.
5173  * \param is_caller Non-zero if chan is the calling channel.
5174  */
5175 static void update_connected_line_from_peer(struct ast_channel *chan, struct ast_channel *peer, int is_caller)
5176 {
5177  struct ast_party_connected_line connected_caller;
5178 
5179  ast_party_connected_line_init(&connected_caller);
5180 
5181  ast_channel_lock(peer);
5182  ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(peer));
5183  ast_channel_unlock(peer);
5184  connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
5185  if (ast_channel_connected_line_sub(peer, chan, &connected_caller, 0)) {
5186  ast_channel_update_connected_line(chan, &connected_caller, NULL);
5187  }
5188  ast_party_connected_line_free(&connected_caller);
5189 }
5190 
5191 #define AST_MAX_WATCHERS 256
5192 /*!
5193  * \brief Wait for a member to answer the call
5194  *
5195  * \param[in] qe the queue_ent corresponding to the caller in the queue
5196  * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
5197  * \param[in] to the amount of time (in milliseconds) to wait for a response
5198  * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
5199  * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
5200  * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
5201  * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
5202  *
5203  * \todo eventually all call forward logic should be integrated into and replaced by ast_call_forward()
5204  */
5205 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
5206 {
5207  const char *queue = qe->parent->name;
5208  struct callattempt *o, *start = NULL, *prev = NULL;
5209  int status;
5210  int numbusies = prebusies;
5211  int numnochan = 0;
5212  int stillgoing = 0;
5213  int orig = *to;
5214  struct ast_frame *f;
5215  struct callattempt *peer = NULL;
5216  struct ast_channel *winner;
5217  struct ast_channel *in = qe->chan;
5218  char on[80] = "";
5219  char membername[80] = "";
5220  long starttime = 0;
5221  long endtime = 0;
5222  char *inchan_name;
5223  struct timeval start_time_tv = ast_tvnow();
5224  int canceled_by_caller = 0; /* 1 when caller hangs up or press digit or press * */
5225 
5226  ast_channel_lock(qe->chan);
5227  inchan_name = ast_strdupa(ast_channel_name(qe->chan));
5228  ast_channel_unlock(qe->chan);
5229 
5230  starttime = (long) time(NULL);
5231 
5232  while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
5233  int numlines, retry, pos = 1;
5234  struct ast_channel *watchers[AST_MAX_WATCHERS];
5235  watchers[0] = in;
5236  start = NULL;
5237 
5238  for (retry = 0; retry < 2; retry++) {
5239  numlines = 0;
5240  for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
5241  if (o->stillgoing) { /* Keep track of important channels */
5242  stillgoing = 1;
5243  if (o->chan) {
5244  if (pos < AST_MAX_WATCHERS) {
5245  watchers[pos++] = o->chan;
5246  }
5247  if (!start) {
5248  start = o;
5249  } else {
5250  prev->call_next = o;
5251  }
5252  prev = o;
5253  }
5254  } else if (prev) {
5255  prev->call_next = NULL;
5256  }
5257  numlines++;
5258  }
5259  if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
5260  (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */) {
5261  break;
5262  }
5263  /* On "ringall" strategy we only move to the next penalty level
5264  when *all* ringing phones are done in the current penalty level */
5265  ring_one(qe, outgoing, &numbusies);
5266  /* and retry... */
5267  }
5268  if (pos == 1 /* not found */) {
5269  if (numlines == (numbusies + numnochan)) {
5270  ast_debug(1, "Everyone is busy at this time\n");
5271  } else {
5272  ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
5273  }
5274  *to = 0;
5275  return NULL;
5276  }
5277 
5278  /* Poll for events from both the incoming channel as well as any outgoing channels */
5279  winner = ast_waitfor_n(watchers, pos, to);
5280 
5281  /* Service all of the outgoing channels */
5282  for (o = start; o; o = o->call_next) {
5283  /* We go with a fixed buffer here instead of using ast_strdupa. Using
5284  * ast_strdupa in a loop like this one can cause a stack overflow
5285  */
5286  char ochan_name[AST_CHANNEL_NAME];
5287 
5288  if (o->chan) {
5289  ast_channel_lock(o->chan);
5290  ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
5291  ast_channel_unlock(o->chan);
5292  }
5293  if (o->stillgoing && (o->chan) && (ast_channel_state(o->chan) == AST_STATE_UP)) {
5294  if (!peer) {
5295  ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
5296  if (o->orig_chan_name
5297  && strcmp(o->orig_chan_name, ochan_name)) {
5298  /*
5299  * The channel name changed so we must generate COLP update.
5300  * Likely because a call pickup channel masqueraded in.
5301  */
5302  update_connected_line_from_peer(in, o->chan, 1);
5303  } else if (!o->block_connected_update) {
5304  if (o->pending_connected_update) {
5305  if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0)) {
5307  }
5308  } else if (!o->dial_callerid_absent) {
5309  update_connected_line_from_peer(in, o->chan, 1);
5310  }
5311  }
5312  if (o->aoc_s_rate_list) {
5313  size_t encoded_size;
5314  struct ast_aoc_encoded *encoded;
5315  if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
5316  ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
5317  ast_aoc_destroy_encoded(encoded);
5318  }
5319  }
5320  peer = o;
5321  }
5322  } else if (o->chan && (o->chan == winner)) {
5323 
5324  ast_copy_string(on, o->member->interface, sizeof(on));
5325  ast_copy_string(membername, o->member->membername, sizeof(membername));
5326 
5327  /* Before processing channel, go ahead and check for forwarding */
5328  if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
5329  ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
5330  ast_channel_publish_dial_forward(qe->chan, o->chan, NULL, NULL,
5331  "CANCEL", ast_channel_call_forward(o->chan));
5332  numnochan++;
5333  do_hang(o);
5334  winner = NULL;
5335  continue;
5336  } else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) {
5337  struct ast_channel *original = o->chan;
5338  char forwarder[AST_CHANNEL_NAME];
5339  char tmpchan[256];
5340  char *stuff;
5341  char *tech;
5342  int failed = 0;
5343 
5344  ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan));
5345  ast_copy_string(forwarder, ast_channel_name(o->chan), sizeof(forwarder));
5346  if ((stuff = strchr(tmpchan, '/'))) {
5347  *stuff++ = '\0';
5348  tech = tmpchan;
5349  } else {
5350  const char *forward_context;
5351  ast_channel_lock(o->chan);
5352  forward_context = pbx_builtin_getvar_helper(o->chan, "FORWARD_CONTEXT");
5353  snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), forward_context ? forward_context : ast_channel_context(o->chan));
5354  ast_channel_unlock(o->chan);
5355  stuff = tmpchan;
5356  tech = "Local";
5357  }
5358  if (!strcasecmp(tech, "Local")) {
5359  /*
5360  * Drop the connected line update block for local channels since
5361  * this is going to run dialplan and the user can change his
5362  * mind about what connected line information he wants to send.
5363  */
5364  o->block_connected_update = 0;
5365  }
5366 
5367  ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
5368  /* Setup parameters */
5369  o->chan = ast_request(tech, ast_channel_nativeformats(in), NULL, in, stuff, &status);
5370  if (!o->chan) {
5371  ast_log(LOG_NOTICE,
5372  "Forwarding failed to create channel to dial '%s/%s'\n",
5373  tech, stuff);
5374  o->stillgoing = 0;
5375  numnochan++;
5376  } else {
5377  ast_channel_lock_both(o->chan, original);
5378  ast_party_redirecting_copy(ast_channel_redirecting(o->chan),
5379  ast_channel_redirecting(original));
5380  ast_channel_unlock(o->chan);
5381  ast_channel_unlock(original);
5382 
5383  ast_channel_lock_both(o->chan, in);
5384  ast_channel_inherit_variables(in, o->chan);
5385  ast_channel_datastore_inherit(in, o->chan);
5386  pbx_builtin_setvar_helper(o->chan, "FORWARDERNAME", forwarder);
5387  ast_max_forwards_decrement(o->chan);
5388 
5389  if (o->pending_connected_update) {
5390  /*
5391  * Re-seed the callattempt's connected line information with
5392  * previously acquired connected line info from the queued
5393  * channel. The previously acquired connected line info could
5394  * have been set through the CONNECTED_LINE dialplan function.
5395  */
5396  o->pending_connected_update = 0;
5397  ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
5398  }
5399 
5400  ast_free(o->orig_chan_name);
5401  o->orig_chan_name = ast_strdup(ast_channel_name(o->chan));
5402 
5404 
5405  if (!ast_channel_redirecting(o->chan)->from.number.valid
5406  || ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
5407  /*
5408  * The call was not previously redirected so it is
5409  * now redirected from this number.
5410  */
5411  ast_party_number_free(&ast_channel_redirecting(o->chan)->from.number);
5412  ast_party_number_init(&ast_channel_redirecting(o->chan)->from.number);
5413  ast_channel_redirecting(o->chan)->from.number.valid = 1;
5414  ast_channel_redirecting(o->chan)->from.number.str =
5415  ast_strdup(ast_channel_exten(in));
5416  }
5417 
5418  ast_channel_dialed(o->chan)->transit_network_select = ast_channel_dialed(in)->transit_network_select;
5419 
5420  o->dial_callerid_absent = !ast_channel_caller(o->chan)->id.number.valid
5421  || ast_strlen_zero(ast_channel_caller(o->chan)->id.number.str);
5422  ast_connected_line_copy_from_caller(ast_channel_connected(o->chan),
5423  ast_channel_caller(in));
5424 
5425  ast_channel_unlock(in);
5426  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL
5427  && !o->block_connected_update) {
5428  struct ast_party_redirecting redirecting;
5429 
5430  /*
5431  * Redirecting updates to the caller make sense only on single
5432  * call at a time strategies.
5433  *
5434  * Need to re-evaluate if calling unlock is still required as we no longer
5435  * use macro.
5436  */
5437  ast_party_redirecting_init(&redirecting);
5438  ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(o->chan));
5439  ast_channel_unlock(o->chan);
5440  if (ast_channel_redirecting_sub(o->chan, in, &redirecting, 0)) {
5441  ast_channel_update_redirecting(in, &redirecting, NULL);
5442  }
5443  ast_party_redirecting_free(&redirecting);
5444  } else {
5445  ast_channel_unlock(o->chan);
5446  }
5447 
5448  if (ast_call(o->chan, stuff, 0)) {
5449  ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
5450  tech, stuff);
5451  failed = 1;
5452  }
5453  }
5454 
5455  ast_channel_publish_dial_forward(qe->chan, original, o->chan, NULL,
5456  "CANCEL", ast_channel_call_forward(original));
5457  if (o->chan) {
5458  ast_channel_publish_dial(qe->chan, o->chan, stuff, NULL);
5459  }
5460 
5461  if (failed) {
5462  do_hang(o);
5463  numnochan++;
5464  }
5465 
5466  /* Hangup the original channel now, in case we needed it */
5467  ast_hangup(winner);
5468  continue;
5469  }
5470  f = ast_read(winner);
5471  if (f) {
5472  if (f->frametype == AST_FRAME_CONTROL) {
5473  switch (f->subclass.integer) {
5474  case AST_CONTROL_ANSWER:
5475  /* This is our guy if someone answered. */
5476  if (!peer) {
5477  ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
5478  ast_channel_publish_dial(qe->chan, o->chan, on, "ANSWER");
5479  publish_dial_end_event(qe->chan, outgoing, o->chan, "CANCEL");
5480  if (o->orig_chan_name
5481  && strcmp(o->orig_chan_name, ochan_name)) {
5482  /*
5483  * The channel name changed so we must generate COLP update.
5484  * Likely because a call pickup channel masqueraded in.
5485  */
5486  update_connected_line_from_peer(in, o->chan, 1);
5487  } else if (!o->block_connected_update) {
5488  if (o->pending_connected_update) {
5489  if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0)) {
5491  }
5492  } else if (!o->dial_callerid_absent) {
5493  update_connected_line_from_peer(in, o->chan, 1);
5494  }
5495  }
5496  if (o->aoc_s_rate_list) {
5497  size_t encoded_size;
5498  struct ast_aoc_encoded *encoded;
5499  if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
5500  ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
5501  ast_aoc_destroy_encoded(encoded);
5502  }
5503  }
5504  peer = o;
5505  }
5506  break;
5507  case AST_CONTROL_BUSY:
5508  ast_verb(3, "%s is busy\n", ochan_name);
5509  ast_channel_publish_dial(qe->chan, o->chan, on, "BUSY");
5510  endtime = (long) time(NULL);
5511  endtime -= starttime;
5512  rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopausebusy);
5513  do_hang(o);
5514  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
5515  if (qe->parent->timeoutrestart) {
5516  start_time_tv = ast_tvnow();
5517  }
5518  /* Have enough time for a queue member to answer? */
5519  if (ast_remaining_ms(start_time_tv, orig) > 500) {
5520  ring_one(qe, outgoing, &numbusies);
5521  starttime = (long) time(NULL);
5522  }
5523  }
5524  numbusies++;
5525  break;
5527  ast_verb(3, "%s is circuit-busy\n", ochan_name);
5528  ast_channel_publish_dial(qe->chan, o->chan, on, "CONGESTION");
5529  endtime = (long) time(NULL);
5530  endtime -= starttime;
5531  rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopauseunavail);
5532  do_hang(o);
5533  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
5534  if (qe->parent->timeoutrestart) {
5535  start_time_tv = ast_tvnow();
5536  }
5537  if (ast_remaining_ms(start_time_tv, orig) > 500) {
5538  ring_one(qe, outgoing, &numbusies);
5539  starttime = (long) time(NULL);
5540  }
5541  }
5542  numbusies++;
5543  break;
5544  case AST_CONTROL_RINGING:
5545  ast_verb(3, "%s is ringing\n", ochan_name);
5546 
5547  ast_channel_publish_dial(qe->chan, o->chan, on, "RINGING");
5548 
5549  /* Start ring indication when the channel is ringing, if specified */
5550  if (qe->ring_when_ringing) {
5551  ast_moh_stop(qe->chan);
5553  }
5554  break;
5555  case AST_CONTROL_OFFHOOK:
5556  /* Ignore going off hook */
5557  break;
5559  if (o->block_connected_update) {
5560  ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
5561  break;
5562  }
5563  if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
5564  struct ast_party_connected_line connected;
5565 
5566  ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
5568  ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
5569  ast_party_connected_line_set(&o->connected, &connected, NULL);
5570  ast_party_connected_line_free(&connected);
5571  o->pending_connected_update = 1;
5572  break;
5573  }
5574 
5575  /*
5576  * Prevent using the CallerID from the outgoing channel since we
5577  * got a connected line update from it.
5578  */
5579  o->dial_callerid_absent = 1;
5580 
5581  if (ast_channel_connected_line_sub(o->chan, in, f, 1)) {
5583  }
5584  break;
5585  case AST_CONTROL_AOC:
5586  {
5587  struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
5588  if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
5589  ast_aoc_destroy_decoded(o->aoc_s_rate_list);
5590  o->aoc_s_rate_list = decoded;
5591  } else {
5592  ast_aoc_destroy_decoded(decoded);
5593  }
5594  }
5595  break;
5597  if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
5598  /*
5599  * Redirecting updates to the caller make sense only on single
5600  * call at a time strategies.
5601  */
5602  break;
5603  }
5604  if (o->block_connected_update) {
5605  ast_verb(3, "Redirecting update to %s prevented\n",
5606  inchan_name);
5607  break;
5608  }
5609  ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
5610  ochan_name, inchan_name);
5611  if (ast_channel_redirecting_sub(o->chan, in, f, 1)) {
5613  }
5614  break;
5617  break;
5618  default:
5619  ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
5620  break;
5621  }
5622  }
5623  ast_frfree(f);
5624  } else { /* ast_read() returned NULL */
5625  endtime = (long) time(NULL) - starttime;
5626  ast_channel_publish_dial(qe->chan, o->chan, on, "NOANSWER");
5627  rna(endtime * 1000, qe, o->chan, on, membername, 1);
5628  do_hang(o);
5629  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
5630  if (qe->parent->timeoutrestart) {
5631  start_time_tv = ast_tvnow();
5632  }
5633  if (ast_remaining_ms(start_time_tv, orig) > 500) {
5634  ring_one(qe, outgoing, &numbusies);
5635  starttime = (long) time(NULL);
5636  }
5637  }
5638  }
5639  }
5640  }
5641 
5642  /* If we received an event from the caller, deal with it. */
5643  if (winner == in) {
5644  f = ast_read(in);
5645  if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
5646  /* Got hung up */
5647  *to = -1;
5648  if (f) {
5649  if (f->data.uint32) {
5650  ast_channel_hangupcause_set(in, f->data.uint32);
5651  }
5652  ast_frfree(f);
5653  }
5654  canceled_by_caller = 1;
5655  } else if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
5656  ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
5657  *to = 0;
5658  ast_frfree(f);
5659  canceled_by_caller = 1;
5660  } else if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
5661  ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
5662  *to = 0;
5663  *digit = f->subclass.integer;
5664  ast_frfree(f);
5665  canceled_by_caller = 1;
5666  }
5667  /* When caller hung up or pressed * or digit. */
5668  if (canceled_by_caller) {
5669  publish_dial_end_event(in, outgoing, NULL, "CANCEL");
5670  for (o = start; o; o = o->call_next) {
5671  if (o->chan) {
5672  ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), o->member->membername, "RINGCANCELED", "%d", (int) ast_tvdiff_ms(ast_tvnow(), start_time_tv));
5673  }
5674  }
5675  return NULL;
5676  }
5677 
5678  /* Send the frame from the in channel to all outgoing channels. */
5679  for (o = start; o; o = o->call_next) {
5680  if (!o->stillgoing || !o->chan) {
5681  /* This outgoing channel has died so don't send the frame to it. */
5682  continue;
5683  }
5684  switch (f->frametype) {
5685  case AST_FRAME_CONTROL:
5686  switch (f->subclass.integer) {
5688  if (o->block_connected_update) {
5689  ast_verb(3, "Connected line update to %s prevented.\n", ast_channel_name(o->chan));
5690  break;
5691  }
5692  if (ast_channel_connected_line_sub(in, o->chan, f, 1)) {
5693  ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
5694  }
5695  break;
5697  if (o->block_connected_update) {
5698  ast_verb(3, "Redirecting update to %s prevented.\n", ast_channel_name(o->chan));
5699  break;
5700  }
5701  if (ast_channel_redirecting_sub(in, o->chan, f, 1)) {
5702  ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
5703  }
5704  break;
5705  default:
5706  /* We are not going to do anything with this frame. */
5707  goto skip_frame;
5708  }
5709  break;
5710  default:
5711  /* We are not going to do anything with this frame. */
5712  goto skip_frame;
5713  }
5714  }
5715 skip_frame:;
5716 
5717  ast_frfree(f);
5718  }
5719  }
5720 
5721  if (!*to) {
5722  for (o = start; o; o = o->call_next) {
5723  if (o->chan) {
5724  rna(orig, qe, o->chan, o->interface, o->member->membername, 1);
5725  }
5726  }
5727 
5728  publish_dial_end_event(qe->chan, outgoing, NULL, "NOANSWER");
5729  }
5730 
5731  return peer;
5732 }
5733 
5734 /*!
5735  * \brief Check if we should start attempting to call queue members.
5736  *
5737  * A simple process, really. Count the number of members who are available
5738  * to take our call and then see if we are in a position in the queue at
5739  * which a member could accept our call.
5740  *
5741  * \param[in] qe The caller who wants to know if it is his turn
5742  * \retval 0 It is not our turn
5743  * \retval 1 It is our turn
5744  */
5745 static int is_our_turn(struct queue_ent *qe)
5746 {
5747  struct queue_ent *ch;
5748  int res;
5749  int avl;
5750  int idx = 0;
5751  /* This needs a lock. How many members are available to be served? */
5752  ao2_lock(qe->parent);
5753 
5754  avl = num_available_members(qe->parent);
5755 
5756  ch = qe->parent->head;
5757 
5758  ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
5759 
5760  while ((idx < avl) && (ch) && (ch != qe)) {
5761  if (!ch->pending) {
5762  idx++;
5763  }
5764  ch = ch->next;
5765  }
5766 
5767  ao2_unlock(qe->parent);
5768  /* If the queue entry is within avl [the number of available members] calls from the top ...
5769  * Autofill and position check added to support autofill=no (as only calls
5770  * from the front of the queue are valid when autofill is disabled)
5771  */
5772  if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
5773  ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
5774  res = 1;
5775  } else {
5776  ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
5777  res = 0;
5778  }
5779 
5780  /* Update realtime members if this is the first call and number of avalable members is 0 */
5781  if (avl == 0 && qe->pos == 1) {
5782  update_realtime_members(qe->parent);
5783  }
5784 
5785  return res;
5786 }
5787 
5788 /*!
5789  * \brief update rules for queues
5790  *
5791  * Calculate min/max penalties making sure if relative they stay within bounds.
5792  * Update queues penalty and set dialplan vars, goto next list entry.
5793 */
5794 static void update_qe_rule(struct queue_ent *qe)
5795 {
5796  int max_penalty = INT_MAX;
5797 
5798  if (qe->max_penalty != INT_MAX) {
5799  char max_penalty_str[20];
5800 
5801  if (qe->pr->max_relative) {
5802  max_penalty = qe->max_penalty + qe->pr->max_value;
5803  } else {
5804  max_penalty = qe->pr->max_value;
5805  }
5806 
5807  /* a relative change to the penalty could put it below 0 */
5808  if (max_penalty < 0) {
5809  max_penalty = 0;
5810  }
5811 
5812  snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
5813  pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
5814  qe->max_penalty = max_penalty;
5815  ast_debug(3, "Setting max penalty to %d for caller %s since %d seconds have elapsed\n",
5816  qe->max_penalty, ast_channel_name(qe->chan), qe->pr->time);
5817  }
5818 
5819  if (qe->min_penalty != INT_MAX) {
5820  char min_penalty_str[20];
5821  int min_penalty;
5822 
5823  if (qe->pr->min_relative) {
5824  min_penalty = qe->min_penalty + qe->pr->min_value;
5825  } else {
5826  min_penalty = qe->pr->min_value;
5827  }
5828 
5829  /* a relative change to the penalty could put it below 0 */
5830  if (min_penalty < 0) {
5831  min_penalty = 0;
5832  }
5833 
5834  if (max_penalty != INT_MAX && min_penalty > max_penalty) {
5835  min_penalty = max_penalty;
5836  }
5837 
5838  snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
5839  pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
5840  qe->min_penalty = min_penalty;
5841  ast_debug(3, "Setting min penalty to %d for caller %s since %d seconds have elapsed\n",
5842  qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
5843  }
5844 
5845  if (qe->raise_penalty != INT_MAX) {
5846  char raise_penalty_str[20];
5847  int raise_penalty;
5848 
5849  if (qe->pr->raise_relative) {
5850  raise_penalty = qe->raise_penalty + qe->pr->raise_value;
5851  } else {
5852  raise_penalty = qe->pr->raise_value;
5853  }
5854 
5855  /* a relative change to the penalty could put it below 0 */
5856  if (raise_penalty < 0) {
5857  raise_penalty = 0;
5858  }
5859 
5860  if (max_penalty != INT_MAX && raise_penalty > max_penalty) {
5861  raise_penalty = max_penalty;
5862  }
5863 
5864  snprintf(raise_penalty_str, sizeof(raise_penalty_str), "%d", raise_penalty);
5865  pbx_builtin_setvar_helper(qe->chan, "QUEUE_RAISE_PENALTY", raise_penalty_str);
5867  ast_debug(3, "Setting raised penalty to %d for caller %s since %d seconds have elapsed\n",
5868  qe->raise_penalty, ast_channel_name(qe->chan), qe->pr->time);
5869  }
5870 
5871  qe->pr = AST_LIST_NEXT(qe->pr, list);
5872 }
5873 
5874 /*! \brief The waiting areas for callers who are not actively calling members
5875  *
5876  * This function is one large loop. This function will return if a caller
5877  * either exits the queue or it becomes that caller's turn to attempt calling
5878  * queue members. Inside the loop, we service the caller with periodic announcements,
5879  * holdtime announcements, etc. as configured in queues.conf
5880  *
5881  * \retval 0 if the caller's turn has arrived
5882  * \retval -1 if the caller should exit the queue.
5883  */
5884 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
5885 {
5886  int res = 0;
5887 
5888  /* This is the holding pen for callers 2 through maxlen */
5889  for (;;) {
5890 
5891  /* A request to withdraw this call from the queue arrived */
5892  if (qe->withdraw) {
5893  *reason = QUEUE_WITHDRAW;
5894  res = 1;
5895  break;
5896  }
5897 
5898  if (is_our_turn(qe)) {
5899  break;
5900  }
5901 
5902  /* If we have timed out, break out */
5903  if (qe->expire && (time(NULL) >= qe->expire)) {
5904  *reason = QUEUE_TIMEOUT;
5905  break;
5906  }
5907 
5908  if (qe->parent->leavewhenempty) {
5909  int status = 0;
5910 
5911  if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->raise_penalty, qe->parent->leavewhenempty, 0))) {
5912  record_abandoned(qe);
5913  *reason = QUEUE_LEAVEEMPTY;
5914  ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) (time(NULL) - qe->start));
5915  res = -1;
5916  qe->handled = -1;
5917  break;
5918  }
5919  }
5920 
5921  /* Make a position announcement, if enabled */
5922  if (qe->parent->announcefrequency &&
5923  (res = say_position(qe,ringing))) {
5924  break;
5925  }
5926 
5927  /* If we have timed out, break out */
5928  if (qe->expire && (time(NULL) >= qe->expire)) {
5929  *reason = QUEUE_TIMEOUT;
5930  break;
5931  }
5932 
5933  /* Make a periodic announcement, if enabled */
5934  if (qe->parent->periodicannouncefrequency &&
5935  (res = say_periodic_announcement(qe,ringing)))
5936  break;
5937 
5938  /* see if we need to move to the next penalty level for this queue */
5939  while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
5940  update_qe_rule(qe);
5941  }
5942 
5943  /* If we have timed out, break out */
5944  if (qe->expire && (time(NULL) >= qe->expire)) {
5945  *reason = QUEUE_TIMEOUT;
5946  break;
5947  }
5948 
5949  /* Wait a second before checking again */
5950  if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
5951  if (res > 0 && !valid_exit(qe, res)) {
5952  res = 0;
5953  } else {
5954  break;
5955  }
5956  }
5957 
5958  /* If we have timed out, break out */
5959  if (qe->expire && (time(NULL) >= qe->expire)) {
5960  *reason = QUEUE_TIMEOUT;
5961  break;
5962  }
5963  }
5964 
5965  return res;
5966 }
5967 
5968 /*!
5969  * \brief update the queue status
5970  * \retval 0 always
5971 */
5972 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
5973 {
5974  int oldtalktime;
5975  int newtalktime = time(NULL) - starttime;
5976  struct member *mem;
5977  struct call_queue *qtmp;
5978  struct ao2_iterator queue_iter;
5979 
5980  /* It is possible for us to be called when a call has already been considered terminated
5981  * and data updated, so to ensure we only act on the call that the agent is currently in
5982  * we check when the call was bridged.
5983  */
5984  if (!starttime || (member->starttime != starttime)) {
5985  return 0;
5986  }
5987 
5988  if (shared_lastcall) {
5989  queue_iter = ao2_iterator_init(queues, 0);
5990  while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
5991  ao2_lock(qtmp);
5992  if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
5993  time(&mem->lastcall);
5994  mem->calls++;
5995  mem->callcompletedinsl = 0;
5996  mem->starttime = 0;
5997  mem->lastqueue = q;
5998  ao2_ref(mem, -1);
5999  }
6000  ao2_unlock(qtmp);
6001  queue_t_unref(qtmp, "Done with iterator");
6002  }
6003  ao2_iterator_destroy(&queue_iter);
6004  } else {
6005  ao2_lock(q);
6006  time(&member->lastcall);
6007  member->callcompletedinsl = 0;
6008  member->calls++;
6009  member->starttime = 0;
6010  member->lastqueue = q;
6011  ao2_unlock(q);
6012  }
6013  /* Member might never experience any direct status change (local
6014  * channel with forwarding in particular). If that's the case,
6015  * this is the last chance to remove it from pending or subsequent
6016  * calls will not occur.
6017  */
6018  pending_members_remove(member);
6019 
6020  ao2_lock(q);
6021  q->callscompleted++;
6022  if (callcompletedinsl) {
6023  q->callscompletedinsl++;
6024  }
6025  if (q->callscompleted == 1) {
6026  q->talktime = newtalktime;
6027  } else {
6028  /* Calculate talktime using the same exponential average as holdtime code */
6029  oldtalktime = q->talktime;
6030  q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
6031  }
6032  ao2_unlock(q);
6033  return 0;
6034 }
6035 
6036 /*! \brief Calculate the metric of each member in the outgoing callattempts
6037  *
6038  * A numeric metric is given to each member depending on the ring strategy used
6039  * by the queue. Members with lower metrics will be called before members with
6040  * higher metrics
6041  * \retval -1 if penalties are exceeded
6042  * \retval 0 otherwise
6043  */
6044 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
6045 {
6046  /* disregarding penalty on too few members? */
6047  int membercount = ao2_container_count(q->members);
6048  unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
6049  int penalty = mem->penalty;
6050 
6051  if (usepenalty) {
6052  if (qe->raise_penalty != INT_MAX && penalty < qe->raise_penalty) {
6053  /* Low penalty is raised up to the current minimum */
6054  penalty = qe->raise_penalty;
6055  }
6056  if ((qe->max_penalty != INT_MAX && penalty > qe->max_penalty) ||
6057  (qe->min_penalty != INT_MAX && penalty < qe->min_penalty)) {
6058  return -1;
6059  }
6060  } else {
6061  ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
6062  membercount, q->penaltymemberslimit);
6063  }
6064 
6065  switch (q->strategy) {
6066  case QUEUE_STRATEGY_RINGALL:
6067  /* Everyone equal, except for penalty */
6068  tmp->metric = penalty * 1000000 * usepenalty;
6069  break;
6070  case QUEUE_STRATEGY_LINEAR:
6071  if (pos < qe->linpos) {
6072  tmp->metric = 1000 + pos;
6073  } else {
6074  if (pos > qe->linpos) {
6075  /* Indicate there is another priority */
6076  qe->linwrapped = 1;
6077  }
6078  tmp->metric = pos;
6079  }
6080  tmp->metric += penalty * 1000000 * usepenalty;
6081  break;
6082  case QUEUE_STRATEGY_RRORDERED:
6083  case QUEUE_STRATEGY_RRMEMORY:
6084  pos = mem->queuepos;
6085  if (pos < q->rrpos) {
6086  tmp->metric = 1000 + pos;
6087  } else {
6088  if (pos > q->rrpos) {
6089  /* Indicate there is another priority */
6090  q->wrapped = 1;
6091  }
6092  tmp->metric = pos;
6093  }
6094  tmp->metric += penalty * 1000000 * usepenalty;
6095  break;
6096  case QUEUE_STRATEGY_RANDOM:
6097  tmp->metric = ast_random() % 1000;
6098  tmp->metric += penalty * 1000000 * usepenalty;
6099  break;
6100  case QUEUE_STRATEGY_WRANDOM:
6101  tmp->metric = ast_random() % ((1 + penalty) * 1000);
6102  break;
6103  case QUEUE_STRATEGY_FEWESTCALLS:
6104  tmp->metric = mem->calls;
6105  tmp->metric += penalty * 1000000 * usepenalty;
6106  break;
6107  case QUEUE_STRATEGY_LEASTRECENT:
6108  if (!mem->lastcall) {
6109  tmp->metric = 0;
6110  } else {
6111  tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
6112  }
6113  tmp->metric += penalty * 1000000 * usepenalty;
6114  break;
6115  default:
6116  ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
6117  break;
6118  }
6119  return 0;
6120 }
6121 
6122 enum agent_complete_reason {
6123  CALLER,
6124  AGENT,
6125  TRANSFER
6126 };
6127 
6128 /*! \brief Send out AMI message with member call completion status information */
6129 static void send_agent_complete(const char *queuename, struct ast_channel_snapshot *caller,
6130  struct ast_channel_snapshot *peer, const struct member *member, time_t holdstart,
6131  time_t callstart, enum agent_complete_reason rsn)
6132 {
6133  const char *reason = NULL; /* silence dumb compilers */
6134  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
6135 
6136  switch (rsn) {
6137  case CALLER:
6138  reason = "caller";
6139  break;
6140  case AGENT:
6141  reason = "agent";
6142  break;
6143  case TRANSFER:
6144  reason = "transfer";
6145  break;
6146  }
6147 
6148  blob = ast_json_pack("{s: s, s: s, s: s, s: I, s: I, s: s}",
6149  "Queue", queuename,
6150  "Interface", member->interface,
6151  "MemberName", member->membername,
6152  "HoldTime", (ast_json_int_t)(callstart - holdstart),
6153  "TalkTime", (ast_json_int_t)(time(NULL) - callstart),
6154  "Reason", reason ?: "");
6155 
6156  queue_publish_multi_channel_snapshot_blob(ast_queue_topic(queuename), caller, peer,
6157  queue_agent_complete_type(), blob);
6158 }
6159 
6160 static void queue_agent_cb(void *userdata, struct stasis_subscription *sub,
6161  struct stasis_message *msg)
6162 {
6163  struct ast_channel_blob *agent_blob;
6164 
6165  agent_blob = stasis_message_data(msg);
6166 
6168  ast_queue_log("NONE", agent_blob->snapshot->base->uniqueid,
6169  ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
6170  "AGENTLOGIN", "%s", agent_blob->snapshot->base->name);
6171  } else if (ast_channel_agent_logoff_type() == stasis_message_type(msg)) {
6172  ast_queue_log("NONE", agent_blob->snapshot->base->uniqueid,
6173  ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
6174  "AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->base->name,
6175  (long) ast_json_integer_get(ast_json_object_get(agent_blob->blob, "logintime")));
6176  }
6177 }
6178 
6179 /*!
6180  * \brief Structure representing relevant data during a local channel optimization
6181  *
6182  * The reason we care about local channel optimizations is that we want to be able
6183  * to accurately report when the caller and queue member have stopped talking to
6184  * each other. A local channel optimization can cause it to appear that the conversation
6185  * has stopped immediately after it has begun. By tracking that the relevant channels
6186  * to monitor have changed due to a local channel optimization, we can give accurate
6187  * reports.
6188  *
6189  * Local channel optimizations for queues are restricted from their normal operation.
6190  * Bridges created by queues can only be the destination of local channel optimizations,
6191  * not the source. In addition, move-swap local channel optimizations are the only
6192  * permitted types of local channel optimization.
6193  *
6194  * This data is populated when we are told that a local channel optimization begin
6195  * is occurring. When we get told the optimization has ended successfully, we then
6196  * apply the data here into the queue_stasis_data.
6197  */
6199  /*! The uniqueid of the channel that will be taking the place of the caller or member */
6201  /*! Indication of whether we think there is a local channel optimization in progress */
6203  /*! The identifier for this local channel optimization */
6204  unsigned int id;
6205 };
6206 
6207 /*!
6208  * \brief User data for stasis subscriptions used for queue calls.
6209  *
6210  * app_queue subscribes to channel and bridge events for all bridged calls.
6211  * app_queue cares about the following events:
6212  *
6213  * \li bridge enter: To determine the unique ID of the bridge created for the call.
6214  * \li blind transfer: To send an appropriate agent complete event.
6215  * \li attended transfer: To send an appropriate agent complete event.
6216  * \li local optimization: To update caller and member unique IDs for the call.
6217  * \li hangup: To send an appropriate agent complete event.
6218  *
6219  * The stasis subscriptions last until we determine that the caller and the member
6220  * are no longer bridged with each other.
6221  */
6224  /*! The unique ID of the caller's channel. */
6225  AST_STRING_FIELD(caller_uniqueid);
6226  /*! The unique ID of the queue member's channel */
6227  AST_STRING_FIELD(member_uniqueid);
6228  /*! The unique ID of the bridge created by the queue */
6229  AST_STRING_FIELD(bridge_uniqueid);
6230  );
6231  /*! The relevant queue */
6233  /*! The queue member that has answered the call */
6234  struct member *member;
6235  /*! The time at which the caller entered the queue. Start of the caller's hold time */
6236  time_t holdstart;
6237  /*! The time at which the member answered the call. */
6238  time_t starttime;
6239  /*! The original position of the caller when he entered the queue */
6241  /*! Indication if the call was answered within the configured service level of the queue */
6243  /*! Indicates if the stasis subscriptions are shutting down */
6244  int dying;
6245  /*! The stasis message router for bridge events */
6247  /*! The stasis message router for channel events */
6249  /*! Local channel optimization details for the caller */
6250  struct local_optimization caller_optimize;
6251  /*! Local channel optimization details for the member */
6252  struct local_optimization member_optimize;
6253 };
6254 
6255 /*!
6256  * \internal
6257  * \brief Free memory for a queue_stasis_data
6258  */
6259 static void queue_stasis_data_destructor(void *obj)
6260 {
6261  struct queue_stasis_data *queue_data = obj;
6262 
6263  /* This can only happen if refcounts for this object have got severely messed up */
6264  ast_assert(queue_data->bridge_router == NULL);
6265  ast_assert(queue_data->channel_router == NULL);
6266 
6267  ao2_cleanup(queue_data->member);
6268  queue_unref(queue_data->queue);
6269  ast_string_field_free_memory(queue_data);
6270 }
6271 
6272 /*!
6273  * \internal
6274  * \brief End all stasis subscriptions on a queue_stasis_data
6275  */
6276 static void remove_stasis_subscriptions(struct queue_stasis_data *queue_data)
6277 {
6278  SCOPED_AO2LOCK(lock, queue_data);
6279 
6280  queue_data->dying = 1;
6282  queue_data->bridge_router = NULL;
6284  queue_data->channel_router = NULL;
6285 }
6286 
6287 /*!
6288  * \internal
6289  * \brief Allocate a queue_stasis_data and initialize its data.
6290  */
6291 static struct queue_stasis_data *queue_stasis_data_alloc(struct queue_ent *qe,
6292  struct ast_channel *peer, struct member *mem, time_t holdstart,
6293  time_t starttime, int callcompletedinsl)
6294 {
6295  struct queue_stasis_data *queue_data;
6296 
6297  queue_data = ao2_alloc(sizeof(*queue_data), queue_stasis_data_destructor);
6298  if (!queue_data) {
6299  return NULL;
6300  }
6301 
6302  if (ast_string_field_init(queue_data, 64)) {
6303  ao2_cleanup(queue_data);
6304  return NULL;
6305  }
6306 
6307  ast_string_field_set(queue_data, caller_uniqueid, ast_channel_uniqueid(qe->chan));
6308  ast_string_field_set(queue_data, member_uniqueid, ast_channel_uniqueid(peer));
6309  queue_data->queue = queue_ref(qe->parent);
6310  queue_data->starttime = starttime;
6311  queue_data->holdstart = holdstart;
6312  queue_data->callcompletedinsl = callcompletedinsl;
6313  queue_data->caller_pos = qe->opos;
6314  ao2_ref(mem, +1);
6315  queue_data->member = mem;
6316 
6317  return queue_data;
6318 }
6319 
6320 /*!
6321  * \internal
6322  * \brief Log an attended transfer in the queue log.
6323  *
6324  * Attended transfer queue log messages vary based on the method by which the
6325  * attended transfer was completed.
6326  *
6327  * \param queue_data Data pertaining to the particular call in the queue.
6328  * \param atxfer_msg The stasis attended transfer message data.
6329  */
6330 static void log_attended_transfer(struct queue_stasis_data *queue_data,
6331  struct ast_attended_transfer_message *atxfer_msg)
6332 {
6333  RAII_VAR(struct ast_str *, transfer_str, ast_str_create(32), ast_free);
6334 
6335  if (!transfer_str) {
6336  ast_log(LOG_WARNING, "Unable to log attended transfer to queue log\n");
6337  return;
6338  }
6339 
6340  switch (atxfer_msg->dest_type) {
6341  case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
6342  ast_str_set(&transfer_str, 0, "BRIDGE|%s", atxfer_msg->dest.bridge);
6343  break;
6344  case AST_ATTENDED_TRANSFER_DEST_APP:
6345  case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
6346  ast_str_set(&transfer_str, 0, "APP|%s", atxfer_msg->dest.app);
6347  break;
6348  case AST_ATTENDED_TRANSFER_DEST_LINK:
6349  ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->base->name,
6350  atxfer_msg->dest.links[1]->base->name);
6351  break;
6352  case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
6353  case AST_ATTENDED_TRANSFER_DEST_FAIL:
6354  /* Threeways are headed off and should not be logged here */
6355  ast_assert(0);
6356  return;
6357  }
6358 
6359  ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",
6360  ast_str_buffer(transfer_str),
6361  (long) (queue_data->starttime - queue_data->holdstart),
6362  (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
6363 }
6364 
6365 /*!
6366  * \internal
6367  * \brief Handle a stasis bridge enter event.
6368  *
6369  * We track this particular event in order to learn what bridge
6370  * was created for the queue call.
6371  *
6372  * \param userdata Data pertaining to the particular call in the queue.
6373  * \param sub The stasis subscription on which the message occurred.
6374  * \param msg The stasis message for the bridge enter event
6375  */
6376 static void handle_bridge_enter(void *userdata, struct stasis_subscription *sub,
6377  struct stasis_message *msg)
6378 {
6379  struct queue_stasis_data *queue_data = userdata;
6380  struct ast_bridge_blob *enter_blob = stasis_message_data(msg);
6381  SCOPED_AO2LOCK(lock, queue_data);
6382 
6383  if (queue_data->dying) {
6384  return;
6385  }
6386 
6387  if (!ast_strlen_zero(queue_data->bridge_uniqueid)) {
6388  return;
6389  }
6390 
6391  if (!strcmp(enter_blob->channel->base->uniqueid, queue_data->caller_uniqueid)) {
6392  ast_string_field_set(queue_data, bridge_uniqueid,
6393  enter_blob->bridge->uniqueid);
6394  ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",
6395  enter_blob->channel->base->name, queue_data->bridge_uniqueid);
6396  }
6397 }
6398 
6399 /*!
6400  * \brief Handle a blind transfer event
6401  *
6402  * This event is important in order to be able to log the end of the
6403  * call to the queue log and to stasis.
6404  *
6405  * \param userdata Data pertaining to the particular call in the queue.
6406  * \param sub The stasis subscription on which the message occurred.
6407  * \param msg The stasis message for the blind transfer event
6408  */
6409 static void handle_blind_transfer(void *userdata, struct stasis_subscription *sub,
6410  struct stasis_message *msg)
6411 {
6412  struct queue_stasis_data *queue_data = userdata;
6413  struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
6414  const char *exten;
6415  const char *context;
6416  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6417  RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6418 
6419  if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
6420  return;
6421  }
6422 
6423  ao2_lock(queue_data);
6424 
6425  if (queue_data->dying) {
6426  ao2_unlock(queue_data);
6427  return;
6428  }
6429 
6430  if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
6431  strcmp(queue_data->bridge_uniqueid, transfer_msg->bridge->uniqueid)) {
6432  ao2_unlock(queue_data);
6433  return;
6434  }
6435 
6436  caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6437  member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6438 
6439  ao2_unlock(queue_data);
6440 
6441  exten = transfer_msg->exten;
6442  context = transfer_msg->context;
6443 
6444  ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
6445  ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
6446  "BLINDTRANSFER", "%s|%s|%ld|%ld|%d",
6447  exten, context,
6448  (long) (queue_data->starttime - queue_data->holdstart),
6449  (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
6450 
6451  send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6452  queue_data->holdstart, queue_data->starttime, TRANSFER);
6453  update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6454  queue_data->starttime);
6455  remove_stasis_subscriptions(queue_data);
6456 }
6457 
6458 /*!
6459  * \brief Handle an attended transfer event
6460  *
6461  * This event is important in order to be able to log the end of the
6462  * call to the queue log and to stasis.
6463  *
6464  * \param userdata Data pertaining to the particular call in the queue.
6465  * \param sub The stasis subscription on which the message occurred.
6466  * \param msg The stasis message for the attended transfer event.
6467  */
6468 static void handle_attended_transfer(void *userdata, struct stasis_subscription *sub,
6469  struct stasis_message *msg)
6470 {
6471  struct queue_stasis_data *queue_data = userdata;
6472  struct ast_attended_transfer_message *atxfer_msg = stasis_message_data(msg);
6473  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6474  RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6475 
6476  if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS ||
6477  atxfer_msg->dest_type == AST_ATTENDED_TRANSFER_DEST_THREEWAY) {
6478  return;
6479  }
6480 
6481  ao2_lock(queue_data);
6482 
6483  if (queue_data->dying) {
6484  ao2_unlock(queue_data);
6485  return;
6486  }
6487 
6488  if (ast_strlen_zero(queue_data->bridge_uniqueid)) {
6489  ao2_unlock(queue_data);
6490  return;
6491  }
6492 
6493  if ((!atxfer_msg->to_transferee.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6494  atxfer_msg->to_transferee.bridge_snapshot->uniqueid)) &&
6495  (!atxfer_msg->to_transfer_target.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6496  atxfer_msg->to_transfer_target.bridge_snapshot->uniqueid))) {
6497  ao2_unlock(queue_data);
6498  return;
6499  }
6500 
6501  caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6502  member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6503 
6504  ao2_unlock(queue_data);
6505 
6506  ast_debug(3, "Detected attended transfer in queue %s\n", queue_data->queue->name);
6507  log_attended_transfer(queue_data, atxfer_msg);
6508 
6509  send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6510  queue_data->holdstart, queue_data->starttime, TRANSFER);
6511  update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6512  queue_data->starttime);
6513  remove_stasis_subscriptions(queue_data);
6514 }
6515 
6516 /*!
6517  * \internal
6518  * \brief Callback for all stasis bridge events
6519  *
6520  * Based on the event and what bridge it is on, the task is farmed out to relevant
6521  * subroutines for further processing.
6522  */
6523 static void queue_bridge_cb(void *userdata, struct stasis_subscription *sub,
6524  struct stasis_message *msg)
6525 {
6526  if (stasis_subscription_final_message(sub, msg)) {
6527  ao2_cleanup(userdata);
6528  }
6529 }
6530 
6531 /*!
6532  * \internal
6533  * \brief Handler for the beginning of a local channel optimization
6534  *
6535  * This method gathers data relevant to the local channel optimization and stores
6536  * it to be used once the local optimization completes.
6537  *
6538  * \param userdata Data pertaining to the particular call in the queue.
6539  * \param sub The stasis subscription on which the message occurred.
6540  * \param msg The stasis message for the local optimization begin event
6541  */
6542 static void handle_local_optimization_begin(void *userdata, struct stasis_subscription *sub,
6543  struct stasis_message *msg)
6544 {
6545  struct queue_stasis_data *queue_data = userdata;
6546  struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
6547  struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
6548  struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
6549  struct ast_channel_snapshot *source = ast_multi_channel_blob_get_channel(optimization_blob, "source");
6550  struct local_optimization *optimization;
6551  unsigned int id;
6552  SCOPED_AO2LOCK(lock, queue_data);
6553 
6554  if (queue_data->dying) {
6555  return;
6556  }
6557 
6558  if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {
6559  optimization = &queue_data->member_optimize;
6560  } else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {
6561  optimization = &queue_data->caller_optimize;
6562  } else {
6563  return;
6564  }
6565 
6566  /* We only allow move-swap optimizations, so there had BETTER be a source */
6567  ast_assert(source != NULL);
6568 
6569  optimization->source_chan_uniqueid = ast_strdup(source->base->uniqueid);
6570  if (!optimization->source_chan_uniqueid) {
6571  ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->base->name);
6572  return;
6573  }
6575 
6576  optimization->id = id;
6577  optimization->in_progress = 1;
6578 }
6579 
6580 /*!
6581  * \internal
6582  * \brief Handler for the end of a local channel optimization
6583  *
6584  * This method takes the data gathered during the local channel optimization begin
6585  * event and applies it to the queue stasis data appropriately. This generally involves
6586  * updating the caller or member unique ID with the channel that is taking the place of
6587  * the previous caller or member.
6588  *
6589  * \param userdata Data pertaining to the particular call in the queue.
6590  * \param sub The stasis subscription on which the message occurred.
6591  * \param msg The stasis message for the local optimization end event
6592  */
6593 static void handle_local_optimization_end(void *userdata, struct stasis_subscription *sub,
6594  struct stasis_message *msg)
6595 {
6596  struct queue_stasis_data *queue_data = userdata;
6597  struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
6598  struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
6599  struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
6600  struct local_optimization *optimization;
6601  int is_caller;
6602  unsigned int id;
6603  SCOPED_AO2LOCK(lock, queue_data);
6604 
6605  if (queue_data->dying) {
6606  return;
6607  }
6608 
6609  if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {
6610  optimization = &queue_data->member_optimize;
6611  is_caller = 0;
6612  } else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {
6613  optimization = &queue_data->caller_optimize;
6614  is_caller = 1;
6615  } else {
6616  return;
6617  }
6618 
6620 
6621  if (!optimization->in_progress) {
6622  ast_log(LOG_WARNING, "Told of a local optimization end when we had no previous begin\n");
6623  return;
6624  }
6625 
6626  if (id != optimization->id) {
6627  ast_log(LOG_WARNING, "Local optimization end event ID does not match begin (%u != %u)\n",
6628  id, optimization->id);
6629  return;
6630  }
6631 
6632  if (is_caller) {
6633  ast_debug(3, "Local optimization: Changing queue caller uniqueid from %s to %s\n",
6634  queue_data->caller_uniqueid, optimization->source_chan_uniqueid);
6635  ast_string_field_set(queue_data, caller_uniqueid, optimization->source_chan_uniqueid);
6636  } else {
6637  ast_debug(3, "Local optimization: Changing queue member uniqueid from %s to %s\n",
6638  queue_data->member_uniqueid, optimization->source_chan_uniqueid);
6639  ast_string_field_set(queue_data, member_uniqueid, optimization->source_chan_uniqueid);
6640  }
6641 
6642  optimization->in_progress = 0;
6643 }
6644 
6645 /*!
6646  * \internal
6647  * \brief Handler for hangup stasis event
6648  *
6649  * This is how we determine that the caller or member has hung up and the call
6650  * has ended. An appropriate queue log and stasis message are raised in this
6651  * callback.
6652  *
6653  * \param userdata Data pertaining to the particular call in the queue.
6654  * \param sub The stasis subscription on which the message occurred.
6655  * \param msg The stasis message for the hangup event.
6656  */
6657 static void handle_hangup(void *userdata, struct stasis_subscription *sub,
6658  struct stasis_message *msg)
6659 {
6660  struct queue_stasis_data *queue_data = userdata;
6661  struct ast_channel_blob *channel_blob = stasis_message_data(msg);
6662  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6663  RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6664  RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
6665  enum agent_complete_reason reason;
6666 
6667  ao2_lock(queue_data);
6668 
6669  if (queue_data->dying) {
6670  ao2_unlock(queue_data);
6671  return;
6672  }
6673 
6674  if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->caller_uniqueid)) {
6675  reason = CALLER;
6676  } else if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->member_uniqueid)) {
6677  reason = AGENT;
6678  } else {
6679  ao2_unlock(queue_data);
6680  return;
6681  }
6682 
6683  chan = ast_channel_get_by_name(channel_blob->snapshot->base->name);
6684  if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||
6685  !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||
6686  !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {
6687  /* Channel that is hanging up is doing it as part of a transfer.
6688  * We'll get a transfer event later
6689  */
6690  ao2_unlock(queue_data);
6691  return;
6692  }
6693 
6694  caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6695  member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6696 
6697  ao2_unlock(queue_data);
6698 
6699  ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",
6700  channel_blob->snapshot->base->name);
6701 
6702  ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
6703  reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",
6704  (long) (queue_data->starttime - queue_data->holdstart),
6705  (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
6706 
6707  send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6708  queue_data->holdstart, queue_data->starttime, reason);
6709  update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6710  queue_data->starttime);
6711  remove_stasis_subscriptions(queue_data);
6712 }
6713 
6714 static void handle_masquerade(void *userdata, struct stasis_subscription *sub,
6715  struct stasis_message *msg)
6716 {
6717  struct queue_stasis_data *queue_data = userdata;
6718  struct ast_channel_blob *channel_blob = stasis_message_data(msg);
6719  const char *new_channel_id;
6720 
6721  new_channel_id = ast_json_string_get(ast_json_object_get(channel_blob->blob, "newchanneluniqueid"));
6722 
6723  ao2_lock(queue_data);
6724 
6725  if (queue_data->dying) {
6726  ao2_unlock(queue_data);
6727  return;
6728  }
6729 
6730  if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->caller_uniqueid)) {
6731  ast_debug(1, "Replacing caller channel %s with %s due to masquerade\n", queue_data->caller_uniqueid, new_channel_id);
6732  ast_string_field_set(queue_data, caller_uniqueid, new_channel_id);
6733  } else if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->member_uniqueid)) {
6734  ast_debug(1, "Replacing member channel %s with %s due to masquerade\n", queue_data->member_uniqueid, new_channel_id);
6735  ast_string_field_set(queue_data, member_uniqueid, new_channel_id);
6736  }
6737 
6738  ao2_unlock(queue_data);
6739 }
6740 
6741 /*!
6742  * \internal
6743  * \brief Callback for all stasis channel events
6744  *
6745  * Based on the event and the channels involved, the work is farmed out into
6746  * subroutines for further processing.
6747  */
6748 static void queue_channel_cb(void *userdata, struct stasis_subscription *sub,
6749  struct stasis_message *msg)
6750 {
6751  if (stasis_subscription_final_message(sub, msg)) {
6752  ao2_cleanup(userdata);
6753  }
6754 }
6755 
6756 /*!
6757  * \internal
6758  * \brief Create stasis subscriptions for a particular call in the queue.
6759  *
6760  * These subscriptions are created once the call has been answered. The subscriptions
6761  * are put in place so that call progress may be tracked. Once the call can be determined
6762  * to have ended, then messages are logged to the queue log and stasis events are emitted.
6763  *
6764  * \param qe The queue entry representing the caller
6765  * \param peer The channel that has answered the call
6766  * \param mem The queue member that answered the call
6767  * \param holdstart The time at which the caller entered the queue
6768  * \param starttime The time at which the call was answered
6769  * \param callcompletedinsl Indicates if the call was answered within the configured service level of the queue.
6770  * \retval 0 Success
6771  * \retval non-zero Failure
6772  */
6773 static int setup_stasis_subs(struct queue_ent *qe, struct ast_channel *peer, struct member *mem,
6774  time_t holdstart, time_t starttime, int callcompletedinsl)
6775 {
6776  struct queue_stasis_data *queue_data = queue_stasis_data_alloc(qe, peer, mem, holdstart, starttime, callcompletedinsl);
6777 
6778  if (!queue_data) {
6779  return -1;
6780  }
6781 
6782  queue_data->bridge_router = stasis_message_router_create_pool(ast_bridge_topic_all());
6783  if (!queue_data->bridge_router) {
6784  ao2_ref(queue_data, -1);
6785  return -1;
6786  }
6787 
6788  stasis_message_router_add(queue_data->bridge_router, ast_channel_entered_bridge_type(),
6789  handle_bridge_enter, queue_data);
6790  stasis_message_router_add(queue_data->bridge_router, ast_blind_transfer_type(),
6791  handle_blind_transfer, queue_data);
6792  stasis_message_router_add(queue_data->bridge_router, ast_attended_transfer_type(),
6793  handle_attended_transfer, queue_data);
6795  queue_bridge_cb, queue_data);
6796 
6797  queue_data->channel_router = stasis_message_router_create_pool(ast_channel_topic_all());
6798  if (!queue_data->channel_router) {
6799  /* Unsubscribing from the bridge router will remove the only ref of queue_data,
6800  * thus beginning the destruction process
6801  */
6803  queue_data->bridge_router = NULL;
6804  return -1;
6805  }
6806 
6807  ao2_ref(queue_data, +1);
6809  handle_local_optimization_begin, queue_data);
6811  handle_local_optimization_end, queue_data);
6813  handle_hangup, queue_data);
6815  handle_masquerade, queue_data);
6817  queue_channel_cb, queue_data);
6818 
6819  return 0;
6820 }
6821 
6823  struct call_queue *q;
6824  struct ast_channel *chan;
6825 };
6826 
6827 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
6828 {
6829  struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
6830  ao2_ref(qeb, +1);
6831  qeb->chan = originator;
6832 }
6833 
6834 static void end_bridge_callback(void *data)
6835 {
6836  struct queue_end_bridge *qeb = data;
6837  struct call_queue *q = qeb->q;
6838  struct ast_channel *chan = qeb->chan;
6839 
6840  if (ao2_ref(qeb, -1) == 1) {
6841  set_queue_variables(q, chan);
6842  /* This unrefs the reference we made in try_calling when we allocated qeb */
6843  queue_t_unref(q, "Expire bridge_config reference");
6844  }
6845 }
6846 
6847 /*!
6848  * \internal
6849  * \brief Setup the after bridge goto location on the peer.
6850  * \since 12.0.0
6851  *
6852  * \param chan Calling channel for bridge.
6853  * \param peer Peer channel for bridge.
6854  * \param opts Dialing option flags.
6855  * \param opt_args Dialing option argument strings.
6856  */
6857 static void setup_peer_after_bridge_goto(struct ast_channel *chan, struct ast_channel *peer, struct ast_flags *opts, char *opt_args[])
6858 {
6859  const char *context;
6860  const char *extension;
6861  int priority;
6862 
6863  if (ast_test_flag(opts, OPT_CALLEE_GO_ON)) {
6864  ast_channel_lock(chan);
6865  context = ast_strdupa(ast_channel_context(chan));
6866  extension = ast_strdupa(ast_channel_exten(chan));
6867  priority = ast_channel_priority(chan);
6868  ast_channel_unlock(chan);
6869  ast_bridge_set_after_go_on(peer, context, extension, priority,
6870  opt_args[OPT_ARG_CALLEE_GO_ON]);
6871  }
6872 }
6873 
6874 static void escape_and_substitute(struct ast_channel *chan, const char *input,
6875  char *output, size_t size)
6876 {
6877  const char *m = input;
6878  char escaped[size];
6879  char *p;
6880 
6881  for (p = escaped; p < escaped + size - 1; p++, m++) {
6882  switch (*m) {
6883  case '^':
6884  if (*(m + 1) == '{') {
6885  *p = '$';
6886  }
6887  break;
6888  case ',':
6889  *p++ = '\\';
6890  /* Fall through */
6891  default:
6892  *p = *m;
6893  }
6894  if (*m == '\0')
6895  break;
6896  }
6897 
6898  if (p == escaped + size) {
6899  escaped[size - 1] = '\0';
6900  }
6901 
6902  pbx_substitute_variables_helper(chan, escaped, output, size - 1);
6903 }
6904 
6905 static void setup_mixmonitor(struct queue_ent *qe, const char *filename)
6906 {
6907  char escaped_filename[256];
6908  char file_with_ext[sizeof(escaped_filename) + sizeof(qe->parent->monfmt)];
6909  char mixmonargs[1512];
6910  char escaped_monitor_exec[1024];
6911  const char *monitor_options;
6912  const char *monitor_exec;
6913 
6914  escaped_monitor_exec[0] = '\0';
6915 
6916  if (filename) {
6917  escape_and_substitute(qe->chan, filename, escaped_filename, sizeof(escaped_filename));
6918  } else {
6919  ast_copy_string(escaped_filename, ast_channel_uniqueid(qe->chan), sizeof(escaped_filename));
6920  }
6921 
6922  ast_channel_lock(qe->chan);
6923  if ((monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC"))) {
6924  monitor_exec = ast_strdupa(monitor_exec);
6925  }
6926  if ((monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS"))) {
6927  monitor_options = ast_strdupa(monitor_options);
6928  } else {
6929  monitor_options = "";
6930  }
6931  ast_channel_unlock(qe->chan);
6932 
6933  if (monitor_exec) {
6934  escape_and_substitute(qe->chan, monitor_exec, escaped_monitor_exec, sizeof(escaped_monitor_exec));
6935  }
6936 
6937  snprintf(file_with_ext, sizeof(file_with_ext), "%s.%s", escaped_filename, qe->parent->monfmt);
6938 
6939  if (!ast_strlen_zero(escaped_monitor_exec)) {
6940  snprintf(mixmonargs, sizeof(mixmonargs), "b%s,%s", monitor_options, escaped_monitor_exec);
6941  } else {
6942  snprintf(mixmonargs, sizeof(mixmonargs), "b%s", monitor_options);
6943  }
6944 
6945  ast_debug(1, "Arguments being passed to MixMonitor: %s,%s\n", file_with_ext, mixmonargs);
6946 
6947  if (ast_start_mixmonitor(qe->chan, file_with_ext, mixmonargs)) {
6948  ast_log(LOG_WARNING, "Unable to start mixmonitor. Is the MixMonitor app loaded?\n");
6949  }
6950 }
6951 
6952 /*!
6953  * \internal
6954  * \brief A large function which calls members, updates statistics, and bridges the caller and a member
6955  *
6956  * Here is the process of this function
6957  * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
6958  * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member.
6959  * 3. Call ring_one to place a call to the appropriate member(s)
6960  * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
6961  * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
6962  * 6. Start the monitor or mixmonitor if the option is set
6963  * 7. Remove the caller from the queue to allow other callers to advance
6964  * 8. Bridge the call.
6965  * 9. Do any post processing after the call has disconnected.
6966  *
6967  * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
6968  * \param[in] opts the options passed as the third parameter to the Queue() application
6969  * \param[in] opt_args the options passed as the third parameter to the Queue() application
6970  * \param[in] announceoverride filename to play to user when waiting
6971  * \param[in] url the url passed as the fourth parameter to the Queue() application
6972  * \param[in,out] tries the number of times we have tried calling queue members
6973  * \param[out] noption set if the call to Queue() has the 'n' option set.
6974  * \param[in] agi the agi passed as the fifth parameter to the Queue() application
6975  * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
6976  * \param[in] ringing 1 if the 'r' option is set, otherwise 0
6977  */
6978 static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *gosub, int ringing)
6979 {
6980  struct member *cur;
6981  struct callattempt *outgoing = NULL; /* the list of calls we are building */
6982  int to, orig;
6983  char oldexten[AST_MAX_EXTENSION]="";
6984  char oldcontext[AST_MAX_CONTEXT]="";
6985  char queuename[256]="";
6986  struct ast_channel *peer;
6987  struct callattempt *lpeer;
6988  struct member *member;
6989  struct ast_app *application;
6990  int res = 0, bridge = 0;
6991  int numbusies = 0;
6992  int x=0;
6993  char *announce = NULL;
6994  char digit = 0;
6995  time_t now = time(NULL);
6996  struct ast_bridge_config bridge_config;
6997  char nondataquality = 1;
6998  char *agiexec = NULL;
6999  char *gosubexec = NULL;
7000  const char *monitorfilename;
7001  int forwardsallowed = 1;
7002  int block_connected_line = 0;
7003  struct ao2_iterator memi;
7004  struct queue_end_bridge *queue_end_bridge = NULL;
7005  int callcompletedinsl;
7006  time_t starttime;
7007 
7008  memset(&bridge_config, 0, sizeof(bridge_config));
7009  time(&now);
7010 
7011  /* If we've already exceeded our timeout, then just stop
7012  * This should be extremely rare. queue_exec will take care
7013  * of removing the caller and reporting the timeout as the reason.
7014  */
7015  if (qe->expire && now >= qe->expire) {
7016  res = 0;
7017  goto out;
7018  }
7019 
7020  if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER)) {
7021  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
7022  }
7023  if (ast_test_flag(&opts, OPT_CALLER_TRANSFER)) {
7024  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
7025  }
7026  if (ast_test_flag(&opts, OPT_CALLEE_AUTOMON)) {
7027  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
7028  }
7029  if (ast_test_flag(&opts, OPT_CALLER_AUTOMON)) {
7030  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
7031  }
7032  if (ast_test_flag(&opts, OPT_DATA_QUALITY)) {
7033  nondataquality = 0;
7034  }
7035  if (ast_test_flag(&opts, OPT_CALLEE_HANGUP)) {
7036  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
7037  }
7038  if (ast_test_flag(&opts, OPT_CALLER_HANGUP)) {
7039  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
7040  }
7041  if (ast_test_flag(&opts, OPT_CALLEE_PARK)) {
7042  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
7043  }
7044  if (ast_test_flag(&opts, OPT_CALLER_PARK)) {
7045  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
7046  }
7047  if (ast_test_flag(&opts, OPT_NO_RETRY)) {
7048  if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR
7049  || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
7050  (*tries)++;
7051  } else {
7052  *tries = ao2_container_count(qe->parent->members);
7053  }
7054  *noption = 1;
7055  }
7056  if (ast_test_flag(&opts, OPT_IGNORE_CALL_FW)) {
7057  forwardsallowed = 0;
7058  }
7059  if (ast_test_flag(&opts, OPT_IGNORE_CONNECTEDLINE)) {
7060  block_connected_line = 1;
7061  }
7062  if (ast_test_flag(&opts, OPT_CALLEE_AUTOMIXMON)) {
7063  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
7064  }
7065  if (ast_test_flag(&opts, OPT_CALLER_AUTOMIXMON)) {
7066  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
7067  }
7068  if (ast_test_flag(&opts, OPT_MARK_AS_ANSWERED)) {
7069  qe->cancel_answered_elsewhere = 1;
7070  }
7071 
7072  /* if the calling channel has AST_CAUSE_ANSWERED_ELSEWHERE set, make sure this is inherited.
7073  (this is mainly to support unreal/local channels)
7074  */
7075  if (ast_channel_hangupcause(qe->chan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
7076  qe->cancel_answered_elsewhere = 1;
7077  }
7078 
7079  ao2_lock(qe->parent);
7080  ast_debug(1, "%s is trying to call a queue member.\n",
7081  ast_channel_name(qe->chan));
7082  ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
7083  if (!ast_strlen_zero(qe->announce)) {
7084  announce = qe->announce;
7085  }
7086  if (!ast_strlen_zero(announceoverride)) {
7087  announce = announceoverride;
7088  }
7089 
7090  memi = ao2_iterator_init(qe->parent->members, 0);
7091  while ((cur = ao2_iterator_next(&memi))) {
7092  struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
7093  if (!tmp) {
7094  ao2_ref(cur, -1);
7095  ao2_iterator_destroy(&memi);
7096  ao2_unlock(qe->parent);
7097  goto out;
7098  }
7099 
7100  /*
7101  * Seed the callattempt's connected line information with previously
7102  * acquired connected line info from the queued channel. The
7103  * previously acquired connected line info could have been set
7104  * through the CONNECTED_LINE dialplan function.
7105  */
7106  ast_channel_lock(qe->chan);
7107  ast_party_connected_line_copy(&tmp->connected, ast_channel_connected(qe->chan));
7108  ast_channel_unlock(qe->chan);
7109 
7110  tmp->block_connected_update = block_connected_line;
7111  tmp->stillgoing = 1;
7112  tmp->member = cur; /* Place the reference for cur into callattempt. */
7113  ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
7114  /* Calculate the metric for the appropriate strategy. */
7115  if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
7116  /* Put them in the list of outgoing thingies... We're ready now.
7117  XXX If we're forcibly removed, these outgoing calls won't get
7118  hung up XXX */
7119  tmp->q_next = outgoing;
7120  outgoing = tmp;
7121  } else {
7122  callattempt_free(tmp);
7123  }
7124  }
7125  ao2_iterator_destroy(&memi);
7126 
7127  if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
7128  /* Application arguments have higher timeout priority (behaviour for <=1.6) */
7129  if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout)) {
7130  to = (qe->expire - now) * 1000;
7131  } else {
7132  to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
7133  }
7134  } else {
7135  /* Config timeout is higher priority thatn application timeout */
7136  if (qe->expire && qe->expire<=now) {
7137  to = 0;
7138  } else if (qe->parent->timeout) {
7139  to = qe->parent->timeout * 1000;
7140  } else {
7141  to = -1;
7142  }
7143  }
7144  orig = to;
7145  ++qe->pending;
7146  ao2_unlock(qe->parent);
7147  /* Call the queue members with the best metric now. */
7148  ring_one(qe, outgoing, &numbusies);
7149  lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
7150  ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
7151  forwardsallowed);
7152 
7153  ao2_lock(qe->parent);
7154  if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
7155  store_next_rr(qe, outgoing);
7156 
7157  }
7158  if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
7159  store_next_lin(qe, outgoing);
7160  }
7161  ao2_unlock(qe->parent);
7162  peer = lpeer ? lpeer->chan : NULL;
7163  if (!peer) {
7164  qe->pending = 0;
7165  if (to) {
7166  /* Must gotten hung up */
7167  res = -1;
7168  } else {
7169  /* User exited by pressing a digit */
7170  res = digit;
7171  }
7172  if (res == -1) {
7173  ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan));
7174  }
7175  } else { /* peer is valid */
7176  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
7177  RAII_VAR(struct ast_str *, interfacevar, ast_str_create(325), ast_free);
7178  /* Ah ha! Someone answered within the desired timeframe. Of course after this
7179  we will always return with -1 so that it is hung up properly after the
7180  conversation. */
7181  if (!strcmp(ast_channel_tech(qe->chan)->type, "DAHDI")) {
7182  ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
7183  }
7184  if (!strcmp(ast_channel_tech(peer)->type, "DAHDI")) {
7185  ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
7186  }
7187  /* Update parameters for the queue */
7188  time(&now);
7189  recalc_holdtime(qe, (now - qe->start));
7190  member = lpeer->member;
7191  ao2_lock(qe->parent);
7192  callcompletedinsl = member->callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
7193  ao2_unlock(qe->parent);
7194  /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
7195  ao2_ref(member, 1);
7196  hangupcalls(qe, outgoing, peer, qe->cancel_answered_elsewhere);
7197  outgoing = NULL;
7198  if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
7199  int res2;
7200 
7201  res2 = ast_autoservice_start(qe->chan);
7202  if (!res2) {
7203  if (qe->parent->memberdelay) {
7204  ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
7205  res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
7206  }
7207  if (!res2 && announce) {
7208  char *front;
7209  char *announcefiles = ast_strdupa(announce);
7210  while ((front = ast_strsep(&announcefiles, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) {
7211  if (play_file(peer, front) < 0) {
7212  ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", front, ast_channel_name(peer));
7213  }
7214  }
7215  }
7216  if (!res2 && qe->parent->reportholdtime) {
7217  if (!play_file(peer, qe->parent->sound_reporthold)) {
7218  long holdtime, holdtimesecs;
7219 
7220  time(&now);
7221  holdtime = labs((now - qe->start) / 60);
7222  holdtimesecs = labs((now - qe->start) % 60);
7223  if (holdtime > 0) {
7224  ast_say_number(peer, holdtime, AST_DIGIT_ANY, ast_channel_language(peer), "n");
7225  if (play_file(peer, qe->parent->sound_minutes) < 0) {
7226  ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, ast_channel_name(peer));
7227  }
7228  }
7229  if (holdtimesecs > 1) {
7230  ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), "n");
7231  if (play_file(peer, qe->parent->sound_seconds) < 0) {
7232  ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, ast_channel_name(peer));
7233  }
7234  }
7235  }
7236  }
7238  }
7239  if (ast_check_hangup(peer)) {
7240  /* Agent must have hung up */
7241  ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", ast_channel_name(peer));
7242  ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "AGENTDUMP", "%s", "");
7243 
7244  blob = ast_json_pack("{s: s, s: s, s: s}",
7245  "Queue", queuename,
7246  "Interface", member->interface,
7247  "MemberName", member->membername);
7248  queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_dump_type(), blob);
7249 
7250  ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer)));
7252  pending_members_remove(member);
7253  ao2_ref(member, -1);
7254  goto out;
7255  } else if (ast_check_hangup(qe->chan)) {
7256  /* Caller must have hung up just before being connected */
7257  ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", ast_channel_name(peer));
7258  ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) (time(NULL) - qe->start));
7259  record_abandoned(qe);
7260  qe->handled = -1;
7261  ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer)));
7263  pending_members_remove(member);
7264  ao2_ref(member, -1);
7265  return -1;
7266  }
7267  }
7268  /* Stop music on hold */
7269  if (ringing) {
7270  ast_indicate(qe->chan,-1);
7271  } else {
7272  ast_moh_stop(qe->chan);
7273  }
7274 
7275  /* Make sure channels are compatible */
7276  res = ast_channel_make_compatible(qe->chan, peer);
7277  if (res < 0) {
7278  ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "SYSCOMPAT", "%s", "");
7279  ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(qe->chan), ast_channel_name(peer));
7280  record_abandoned(qe);
7281  ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer)));
7283  pending_members_remove(member);
7284  ao2_ref(member, -1);
7285  return -1;
7286  }
7287 
7288  /* Play announcement to the caller telling it's his turn if defined */
7289  if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
7290  if (play_file(qe->chan, qe->parent->sound_callerannounce)) {
7291  ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
7292  }
7293  }
7294 
7295  ao2_lock(qe->parent);
7296  /* if setinterfacevar is defined, make member variables available to the channel */
7297  /* use pbx_builtin_setvar to set a load of variables with one call */
7298  if (qe->parent->setinterfacevar && interfacevar) {
7299  ast_str_set(&interfacevar, 0, "MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
7300  member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
7301  pbx_builtin_setvar_multiple(qe->chan, ast_str_buffer(interfacevar));
7302  pbx_builtin_setvar_multiple(peer, ast_str_buffer(interfacevar));
7303  }
7304 
7305  /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
7306  /* use pbx_builtin_setvar to set a load of variables with one call */
7307  if (qe->parent->setqueueentryvar && interfacevar) {
7308  ast_str_set(&interfacevar, 0, "QEHOLDTIME=%ld,QEORIGINALPOS=%d",
7309  (long) (time(NULL) - qe->start), qe->opos);
7310  pbx_builtin_setvar_multiple(qe->chan, ast_str_buffer(interfacevar));
7311  pbx_builtin_setvar_multiple(peer, ast_str_buffer(interfacevar));
7312  }
7313 
7314  ao2_unlock(qe->parent);
7315 
7316  /* try to set queue variables if configured to do so*/
7317  set_queue_variables(qe->parent, qe->chan);
7318  set_queue_variables(qe->parent, peer);
7319 
7320  setup_peer_after_bridge_goto(qe->chan, peer, &opts, opt_args);
7321  ast_channel_lock(qe->chan);
7322  if ((monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME"))) {
7323  monitorfilename = ast_strdupa(monitorfilename);
7324  }
7325  ast_channel_unlock(qe->chan);
7326 
7327  /* Begin Monitoring */
7328  if (*qe->parent->monfmt) {
7329  setup_mixmonitor(qe, monitorfilename);
7330  }
7331  /* Drop out of the queue at this point, to prepare for next caller */
7332  leave_queue(qe);
7333  if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
7334  ast_debug(1, "app_queue: sendurl=%s.\n", url);
7335  ast_channel_sendurl(peer, url);
7336  }
7337 
7338  /* run a gosub for this connection if defined. The gosub simply returns, no action is taken on the result */
7339  /* use gosub from dialplan if passed as a option, otherwise use the default queue gosub */
7340  if (!ast_strlen_zero(gosub)) {
7341  gosubexec = ast_strdupa(gosub);
7342  } else {
7343  if (qe->parent->membergosub) {
7344  gosubexec = ast_strdupa(qe->parent->membergosub);
7345  }
7346  }
7347 
7348  if (!ast_strlen_zero(gosubexec)) {
7349  char *gosub_args = NULL;
7350  char *gosub_argstart;
7351 
7352  ast_debug(1, "app_queue: gosub=%s.\n", gosubexec);
7353 
7354  gosub_argstart = strchr(gosubexec, ',');
7355  if (gosub_argstart) {
7356  const char *what_is_s = "s";
7357  *gosub_argstart = 0;
7358  if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
7359  ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
7360  what_is_s = "~~s~~";
7361  }
7362  if (ast_asprintf(&gosub_args, "%s,%s,1(%s)", gosubexec, what_is_s, gosub_argstart + 1) < 0) {
7363  gosub_args = NULL;
7364  }
7365  *gosub_argstart = ',';
7366  } else {
7367  const char *what_is_s = "s";
7368  if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
7369  ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
7370  what_is_s = "~~s~~";
7371  }
7372  if (ast_asprintf(&gosub_args, "%s,%s,1", gosubexec, what_is_s) < 0) {
7373  gosub_args = NULL;
7374  }
7375  }
7376  if (gosub_args) {
7377  ast_app_exec_sub(qe->chan, peer, gosub_args, 0);
7378  ast_free(gosub_args);
7379  } else {
7380  ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
7381  }
7382  }
7383 
7384  if (!ast_strlen_zero(agi)) {
7385  ast_debug(1, "app_queue: agi=%s.\n", agi);
7386  application = pbx_findapp("agi");
7387  if (application) {
7388  agiexec = ast_strdupa(agi);
7389  pbx_exec(qe->chan, application, agiexec);
7390  } else {
7391  ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
7392  }
7393  }
7394  qe->handled++;
7395 
7396  ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) (time(NULL) - qe->start), ast_channel_uniqueid(peer),
7397  (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
7398 
7399  blob = ast_json_pack("{s: s, s: s, s: s, s: I, s: I}",
7400  "Queue", queuename,
7401  "Interface", member->interface,
7402  "MemberName", member->membername,
7403  "HoldTime", (ast_json_int_t)(time(NULL) - qe->start),
7404  "RingTime", (ast_json_int_t)(orig - to > 0 ? (orig - to) / 1000 : 0));
7405  queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_connect_type(), blob);
7406 
7407  ast_copy_string(oldcontext, ast_channel_context(qe->chan), sizeof(oldcontext));
7408  ast_copy_string(oldexten, ast_channel_exten(qe->chan), sizeof(oldexten));
7409 
7410  if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
7411  queue_end_bridge->q = qe->parent;
7412  queue_end_bridge->chan = qe->chan;
7413  bridge_config.end_bridge_callback = end_bridge_callback;
7414  bridge_config.end_bridge_callback_data = queue_end_bridge;
7415  bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
7416  /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
7417  * to make sure to increase the refcount of this queue so it cannot be freed until we
7418  * are done with it. We remove this reference in end_bridge_callback.
7419  */
7420  queue_t_ref(qe->parent, "For bridge_config reference");
7421  }
7422 
7423  ao2_lock(qe->parent);
7424  time(&member->starttime);
7425  starttime = member->starttime;
7426  ao2_unlock(qe->parent);
7427  /* As a queue member may end up in multiple calls at once if a transfer occurs with
7428  * a Local channel in the mix we pass the current call information (starttime) to the
7429  * Stasis subscriptions so when they update the queue member data it becomes a noop
7430  * if this call is no longer between the caller and the queue member.
7431  */
7432  setup_stasis_subs(qe, peer, member, qe->start, starttime, callcompletedinsl);
7433  bridge = ast_bridge_call_with_flags(qe->chan, peer, &bridge_config,
7435 
7436  res = bridge ? bridge : 1;
7437  ao2_ref(member, -1);
7438  }
7439 out:
7440  hangupcalls(qe, outgoing, NULL, qe->cancel_answered_elsewhere);
7441 
7442  return res;
7443 }
7444 
7445 static int wait_a_bit(struct queue_ent *qe)
7446 {
7447  /* Don't need to hold the lock while we setup the outgoing calls */
7448  int retrywait = qe->parent->retry * 1000;
7449 
7450  int res = ast_waitfordigit(qe->chan, retrywait);
7451  if (res > 0 && !valid_exit(qe, res)) {
7452  res = 0;
7453  }
7454 
7455  return res;
7456 }
7457 
7458 static struct member *interface_exists(struct call_queue *q, const char *interface)
7459 {
7460  struct member *mem;
7461  struct ao2_iterator mem_iter;
7462 
7463  if (!q) {
7464  return NULL;
7465  }
7466  mem_iter = ao2_iterator_init(q->members, 0);
7467  while ((mem = ao2_iterator_next(&mem_iter))) {
7468  if (!strcasecmp(interface, mem->interface)) {
7469  ao2_iterator_destroy(&mem_iter);
7470  return mem;
7471  }
7472  ao2_ref(mem, -1);
7473  }
7474  ao2_iterator_destroy(&mem_iter);
7475 
7476  return NULL;
7477 }
7478 
7479 
7480 /*! \brief Dump all members in a specific queue to the database
7481  * \code
7482  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>;<state_interface>[|...]
7483  * \endcode
7484  */
7485 static void dump_queue_members(struct call_queue *pm_queue)
7486 {
7487  struct member *cur_member;
7488  struct ast_str *value;
7489  struct ao2_iterator mem_iter;
7490 
7491  if (!pm_queue) {
7492  return;
7493  }
7494 
7495  /* 4K is a reasonable default for most applications, but we grow to
7496  * accommodate more if necessary. */
7497  if (!(value = ast_str_create(4096))) {
7498  return;
7499  }
7500 
7501  mem_iter = ao2_iterator_init(pm_queue->members, 0);
7502  while ((cur_member = ao2_iterator_next(&mem_iter))) {
7503  if (!cur_member->dynamic) {
7504  ao2_ref(cur_member, -1);
7505  continue;
7506  }
7507 
7508  ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s;%s;%d",
7509  ast_str_strlen(value) ? "|" : "",
7510  cur_member->interface,
7511  cur_member->penalty,
7512  cur_member->paused,
7513  cur_member->membername,
7514  cur_member->state_interface,
7515  cur_member->reason_paused,
7516  cur_member->wrapuptime);
7517 
7518  ao2_ref(cur_member, -1);
7519  }
7520  ao2_iterator_destroy(&mem_iter);
7521 
7522  if (ast_str_strlen(value) && !cur_member) {
7523  if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
7524  ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
7525  }
7526  } else {
7527  /* Delete the entry if the queue is empty or there is an error */
7528  ast_db_del(pm_family, pm_queue->name);
7529  }
7530 
7531  ast_free(value);
7532 }
7533 
7534 /*! \brief Remove member from queue
7535  * \retval RES_NOT_DYNAMIC when they aren't a RT member
7536  * \retval RES_NOSUCHQUEUE queue does not exist
7537  * \retval RES_OKAY removed member from queue
7538  * \retval RES_EXISTS queue exists but no members
7539 */
7540 static int remove_from_queue(const char *queuename, const char *interface)
7541 {
7542  struct call_queue *q, tmpq = {
7543  .name = queuename,
7544  };
7545  struct member *mem, tmpmem;
7546  int res = RES_NOSUCHQUEUE;
7547 
7548  ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
7549  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) {
7550  ao2_lock(q);
7551  if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
7552  /* XXX future changes should beware of this assumption!! */
7553  /*Change Penalty on realtime users*/
7554  if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid) && negative_penalty_invalid) {
7555  update_realtime_member_field(mem, q->name, "penalty", "-1");
7556  } else if (!mem->dynamic) {
7557  ao2_ref(mem, -1);
7558  ao2_unlock(q);
7559  queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
7560  return RES_NOT_DYNAMIC;
7561  }
7562  queue_publish_member_blob(queue_member_removed_type(), queue_member_blob_create(q, mem));
7563 
7564  member_remove_from_queue(q, mem);
7565  ao2_ref(mem, -1);
7566 
7567  if (queue_persistent_members) {
7568  dump_queue_members(q);
7569  }
7570 
7571  if (!num_available_members(q)) {
7573  }
7574 
7575  res = RES_OKAY;
7576  } else {
7577  res = RES_EXISTS;
7578  }
7579  ao2_unlock(q);
7580  queue_t_unref(q, "Expiring temporary reference");
7581  }
7582 
7583  return res;
7584 }
7585 
7586 /*! \brief Add member to queue
7587  * \retval RES_NOT_DYNAMIC when they aren't a RT member
7588  * \retval RES_NOSUCHQUEUE queue does not exist
7589  * \retval RES_OKAY added member from queue
7590  * \retval RES_EXISTS queue exists but no members
7591  * \retval RES_OUT_OF_MEMORY queue exists but not enough memory to create member
7592 */
7593 static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface, const char *reason_paused, int wrapuptime)
7594 {
7595  struct call_queue *q;
7596  struct member *new_member, *old_member;
7597  int res = RES_NOSUCHQUEUE;
7598 
7599  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7600  * short-circuits if the queue is already in memory. */
7601  if (!(q = find_load_queue_rt_friendly(queuename))) {
7602  return res;
7603  }
7604 
7605  ao2_lock(q);
7606  if ((old_member = interface_exists(q, interface)) == NULL) {
7607  if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse, wrapuptime))) {
7608  new_member->dynamic = 1;
7609  if (reason_paused) {
7610  ast_copy_string(new_member->reason_paused, reason_paused, sizeof(new_member->reason_paused));
7611  }
7612  member_add_to_queue(q, new_member);
7613  queue_publish_member_blob(queue_member_added_type(), queue_member_blob_create(q, new_member));
7614 
7615  if (is_member_available(q, new_member)) {
7617  }
7618 
7619  ao2_ref(new_member, -1);
7620  new_member = NULL;
7621 
7622  if (dump) {
7623  dump_queue_members(q);
7624  }
7625 
7626  res = RES_OKAY;
7627  } else {
7628  res = RES_OUTOFMEMORY;
7629  }
7630  } else {
7631  ao2_ref(old_member, -1);
7632  res = RES_EXISTS;
7633  }
7634  ao2_unlock(q);
7635  queue_t_unref(q, "Expiring temporary reference");
7636 
7637  return res;
7638 }
7639 
7640 
7641 /*! \brief Change priority caller into a queue
7642  * \retval RES_NOSUCHQUEUE queue does not exist
7643  * \retval RES_OKAY change priority
7644  * \retval RES_NOT_CALLER queue exists but no caller
7645 */
7646 static int change_priority_caller_on_queue(const char *queuename, const char *caller, int priority, int immediate)
7647 {
7648  struct call_queue *q;
7649  struct queue_ent *current, *prev = NULL, *caller_qe = NULL;
7650  int res = RES_NOSUCHQUEUE;
7651 
7652  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7653  * short-circuits if the queue is already in memory. */
7654  if (!(q = find_load_queue_rt_friendly(queuename))) {
7655  return res;
7656  }
7657 
7658  ao2_lock(q);
7659  res = RES_NOT_CALLER;
7660  for (current = q->head; current; current = current->next) {
7661  if (strcmp(ast_channel_name(current->chan), caller) == 0) {
7662  ast_debug(1, "%s Caller new priority %d in queue %s\n",
7663  caller, priority, queuename);
7664  current->prio = priority;
7665  if (immediate) {
7666  /* This caller is being immediately moved in the queue so remove them */
7667  if (prev) {
7668  prev->next = current->next;
7669  } else {
7670  q->head = current->next;
7671  }
7672  caller_qe = current;
7673  /* The position for all callers is not recalculated in here as it will
7674  * be updated when the moved caller is inserted back into the queue
7675  */
7676  }
7677  res = RES_OKAY;
7678  break;
7679  } else if (immediate) {
7680  prev = current;
7681  }
7682  }
7683 
7684  if (caller_qe) {
7685  int inserted = 0, pos = 0;
7686 
7687  /* If a caller queue entry exists, we are applying their priority immediately
7688  * and have to reinsert them at the correct position.
7689  */
7690  prev = NULL;
7691  current = q->head;
7692  while (current) {
7693  if (!inserted && (caller_qe->prio > current->prio)) {
7694  insert_entry(q, prev, caller_qe, &pos);
7695  inserted = 1;
7696  }
7697 
7698  /* We always update the position as it may have changed */
7699  current->pos = ++pos;
7700 
7701  /* Move to the next caller in the queue */
7702  prev = current;
7703  current = current->next;
7704  }
7705 
7706  if (!inserted) {
7707  insert_entry(q, prev, caller_qe, &pos);
7708  }
7709  }
7710 
7711  ao2_unlock(q);
7712  return res;
7713 }
7714 
7715 
7716 /*! \brief Request to withdraw a caller from a queue
7717  * \retval RES_NOSUCHQUEUE queue does not exist
7718  * \retval RES_OKAY withdraw request sent
7719  * \retval RES_NOT_CALLER queue exists but no caller
7720  * \retval RES_EXISTS a withdraw request was already sent for this caller (channel) and queue
7721 */
7722 static int request_withdraw_caller_from_queue(const char *queuename, const char *caller, const char *withdraw_info)
7723 {
7724  struct call_queue *q;
7725  struct queue_ent *qe;
7726  int res = RES_NOSUCHQUEUE;
7727 
7728  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7729  * short-circuits if the queue is already in memory. */
7730  if (!(q = find_load_queue_rt_friendly(queuename))) {
7731  return res;
7732  }
7733 
7734  ao2_lock(q);
7735  res = RES_NOT_CALLER;
7736  for (qe = q->head; qe; qe = qe->next) {
7737  if (!strcmp(ast_channel_name(qe->chan), caller)) {
7738  if (qe->withdraw) {
7739  ast_debug(1, "Ignoring duplicate withdraw request of caller %s from queue %s\n", caller, queuename);
7740  res = RES_EXISTS;
7741  } else {
7742  ast_debug(1, "Requested withdraw of caller %s from queue %s\n", caller, queuename);
7743  /* It is not possible to change the withdraw info by further withdraw requests for this caller (channel)
7744  in this queue, so we do not need to worry about a memory leak here. */
7745  if (withdraw_info) {
7746  qe->withdraw_info = ast_strdup(withdraw_info);
7747  }
7748  qe->withdraw = 1;
7749  res = RES_OKAY;
7750  }
7751  break;
7752  }
7753  }
7754  ao2_unlock(q);
7755  queue_unref(q);
7756 
7757  return res;
7758 }
7759 
7760 
7761 static int publish_queue_member_pause(struct call_queue *q, struct member *member)
7762 {
7763  struct ast_json *json_blob = queue_member_blob_create(q, member);
7764 
7765  if (!json_blob) {
7766  return -1;
7767  }
7768 
7769  queue_publish_member_blob(queue_member_pause_type(), json_blob);
7770 
7771  return 0;
7772 }
7773 
7774 /*!
7775  * \internal
7776  * \brief Set the pause status of the specific queue member.
7777  *
7778  * \param q Which queue the member belongs.
7779  * \param mem Queue member being paused/unpaused.
7780  * \param reason Why is this happening (Can be NULL/empty for no reason given.)
7781  * \param paused Set to 1 if the member is being paused or 0 to unpause.
7782  *
7783  * \pre The q is locked on entry.
7784  */
7785 static void set_queue_member_pause(struct call_queue *q, struct member *mem, const char *reason, int paused)
7786 {
7787  if (mem->paused == paused) {
7788  ast_debug(1, "%spausing already-%spaused queue member %s:%s\n",
7789  (paused ? "" : "un"), (paused ? "" : "un"), q->name, mem->interface);
7790  }
7791 
7792  if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid)) {
7793  if (realtime_reason_paused) {
7794  if (ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, "reason_paused", S_OR(reason, ""), "paused", paused ? "1" : "0", SENTINEL) < 0) {
7795  ast_log(LOG_WARNING, "Failed update of realtime queue member %s:%s %spause and reason '%s'\n",
7796  q->name, mem->interface, (paused ? "" : "un"), S_OR(reason, ""));
7797  }
7798  } else {
7799  if (ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, "paused", paused ? "1" : "0", SENTINEL) < 0) {
7800  ast_log(LOG_WARNING, "Failed %spause update of realtime queue member %s:%s\n",
7801  (paused ? "" : "un"), q->name, mem->interface);
7802  }
7803  }
7804  }
7805 
7806  mem->paused = paused;
7807  if (paused) {
7808  time(&mem->lastpause); /* update last pause field */
7809  }
7810  if (paused && !ast_strlen_zero(reason)) {
7811  ast_copy_string(mem->reason_paused, reason, sizeof(mem->reason_paused));
7812  } else {
7813  /* We end up filling this in again later (temporarily) but we need it
7814  * empty for now so that the intervening code - specifically
7815  * dump_queue_members() - has the correct view of things. */
7816  mem->reason_paused[0] = '\0';
7817  }
7818 
7819  ast_devstate_changed(mem->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
7820  AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, mem->interface);
7821 
7822  if (queue_persistent_members) {
7823  dump_queue_members(q);
7824  }
7825 
7826  if (is_member_available(q, mem)) {
7828  "Queue:%s_avail", q->name);
7829  } else if (!num_available_members(q)) {
7831  "Queue:%s_avail", q->name);
7832  }
7833 
7834  if (!paused && !ast_strlen_zero(reason)) {
7835  /* Because we've been unpaused with a 'reason' we need to ensure that
7836  * that reason is emitted when the subsequent PauseQueueMember event
7837  * is raised. So temporarily set it on the member and clear it out
7838  * again right after. */
7839  ast_copy_string(mem->reason_paused, reason, sizeof(mem->reason_paused));
7840  }
7841 
7842  ast_queue_log(q->name, "NONE", mem->membername, paused ? "PAUSE" : "UNPAUSE",
7843  "%s", mem->reason_paused);
7844 
7845  publish_queue_member_pause(q, mem);
7846 
7847  if (!paused) {
7848  mem->reason_paused[0] = '\0';
7849  }
7850 }
7851 
7852 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
7853 {
7854  int found = 0;
7855  struct call_queue *q;
7856  struct ao2_iterator queue_iter;
7857 
7858  if (ast_check_realtime("queues")) {
7859  load_realtime_queues(queuename);
7860  }
7861 
7862  queue_iter = ao2_iterator_init(queues, 0);
7863  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
7864  ao2_lock(q);
7865  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
7866  struct member *mem;
7867 
7868  if ((mem = interface_exists(q, interface))) {
7869  /*
7870  * Before we do the PAUSE/UNPAUSE, log if this was a
7871  * PAUSEALL/UNPAUSEALL but only on the first found entry.
7872  */
7873  ++found;
7874  if (found == 1
7875  && ast_strlen_zero(queuename)) {
7876  /*
7877  * XXX In all other cases, we use the queue name,
7878  * but since this affects all queues, we cannot.
7879  */
7880  ast_queue_log("NONE", "NONE", mem->membername,
7881  (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", S_OR(reason, ""));
7882  }
7883 
7884  set_queue_member_pause(q, mem, reason, paused);
7885  ao2_ref(mem, -1);
7886  }
7887 
7888  if (!ast_strlen_zero(queuename)) {
7889  ao2_unlock(q);
7890  queue_t_unref(q, "Done with iterator");
7891  break;
7892  }
7893  }
7894 
7895  ao2_unlock(q);
7896  queue_t_unref(q, "Done with iterator");
7897  }
7898  ao2_iterator_destroy(&queue_iter);
7899 
7900  return found ? RESULT_SUCCESS : RESULT_FAILURE;
7901 }
7902 
7903 /*!
7904  * \internal
7905  * \brief helper function for set_member_penalty - given a queue, sets all member penalties with the interface
7906  * \param[in] q queue which is having its member's penalty changed - must be unlocked prior to calling
7907  * \param[in] interface String of interface used to search for queue members being changed
7908  * \param[in] penalty Value penalty is being changed to for the member.
7909  * \retval 0 if the there is no member with interface belonging to q and no change is made
7910  * \retval 1 if the there is a member with interface belonging to q and changes are made
7911  */
7912 static int set_member_penalty_help_members(struct call_queue *q, const char *interface, int penalty)
7913 {
7914  struct member *mem;
7915  int foundinterface = 0;
7916 
7917  ao2_lock(q);
7918  if ((mem = interface_exists(q, interface))) {
7919  foundinterface++;
7920  if (mem->realtime) {
7921  char rtpenalty[80];
7922 
7923  sprintf(rtpenalty, "%i", penalty);
7924  update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
7925  }
7926 
7927  mem->penalty = penalty;
7928 
7929  ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
7930  queue_publish_member_blob(queue_member_penalty_type(), queue_member_blob_create(q, mem));
7931  ao2_ref(mem, -1);
7932  }
7933  ao2_unlock(q);
7934 
7935  return foundinterface;
7936 }
7937 
7938 /*!
7939  * \internal
7940  * \brief Set the ringinuse value of the specific queue member.
7941  *
7942  * \param q Which queue the member belongs.
7943  * \param mem Queue member being set.
7944  * \param ringinuse Set to 1 if the member is called when inuse.
7945  *
7946  * \pre The q is locked on entry.
7947  */
7948 static void set_queue_member_ringinuse(struct call_queue *q, struct member *mem, int ringinuse)
7949 {
7950  if (mem->realtime) {
7951  update_realtime_member_field(mem, q->name, realtime_ringinuse_field,
7952  ringinuse ? "1" : "0");
7953  }
7954 
7955  mem->ringinuse = ringinuse;
7956 
7957  ast_queue_log(q->name, "NONE", mem->interface, "RINGINUSE", "%d", ringinuse);
7958  queue_publish_member_blob(queue_member_ringinuse_type(), queue_member_blob_create(q, mem));
7959 }
7960 
7961 static int set_member_ringinuse_help_members(struct call_queue *q, const char *interface, int ringinuse)
7962 {
7963  struct member *mem;
7964  int foundinterface = 0;
7965 
7966  ao2_lock(q);
7967  if ((mem = interface_exists(q, interface))) {
7968  foundinterface++;
7969  set_queue_member_ringinuse(q, mem, ringinuse);
7970  ao2_ref(mem, -1);
7971  }
7972  ao2_unlock(q);
7973 
7974  return foundinterface;
7975 }
7976 
7977 static int set_member_value_help_members(struct call_queue *q, const char *interface, int property, int value)
7978 {
7979  switch(property) {
7980  case MEMBER_PENALTY:
7981  return set_member_penalty_help_members(q, interface, value);
7982 
7983  case MEMBER_RINGINUSE:
7984  return set_member_ringinuse_help_members(q, interface, value);
7985 
7986  default:
7987  ast_log(LOG_ERROR, "Attempted to set invalid property\n");
7988  return 0;
7989  }
7990 }
7991 
7992 /*!
7993  * \internal
7994  * \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
7995  * \param[in] queuename If specified, only act on a member if it belongs to this queue
7996  * \param[in] interface Interface of queue member(s) having priority set.
7997  * \param[in] property Which queue property is being set
7998  * \param[in] value Value penalty is being changed to for each member
7999  */
8000 static int set_member_value(const char *queuename, const char *interface, int property, int value)
8001 {
8002  int foundinterface = 0, foundqueue = 0;
8003  struct call_queue *q;
8004  struct ast_config *queue_config = NULL;
8005  struct ao2_iterator queue_iter;
8006 
8007  /* property dependent restrictions on values should be checked in this switch */
8008  switch (property) {
8009  case MEMBER_PENALTY:
8010  if (value < 0 && !negative_penalty_invalid) {
8011  ast_log(LOG_ERROR, "Invalid penalty (%d)\n", value);
8012  return RESULT_FAILURE;
8013  }
8014  }
8015 
8016  if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
8017  if (ast_check_realtime("queues")) {
8018  queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
8019  if (queue_config) {
8020  char *category = NULL;
8021  while ((category = ast_category_browse(queue_config, category))) {
8022  const char *name = ast_variable_retrieve(queue_config, category, "name");
8023  if (ast_strlen_zero(name)) {
8024  ast_log(LOG_WARNING, "Ignoring realtime queue with a NULL or empty 'name.'\n");
8025  continue;
8026  }
8027  if ((q = find_load_queue_rt_friendly(name))) {
8028  foundqueue++;
8029  foundinterface += set_member_value_help_members(q, interface, property, value);
8030  queue_unref(q);
8031  }
8032  }
8033 
8034  ast_config_destroy(queue_config);
8035  }
8036  }
8037 
8038  /* After hitting realtime queues, go back and get the regular ones. */
8039  queue_iter = ao2_iterator_init(queues, 0);
8040  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
8041  foundqueue++;
8042  foundinterface += set_member_value_help_members(q, interface, property, value);
8043  queue_unref(q);
8044  }
8045  ao2_iterator_destroy(&queue_iter);
8046  } else { /* We actually have a queuename, so we can just act on the single queue. */
8047  if ((q = find_load_queue_rt_friendly(queuename))) {
8048  foundqueue++;
8049  foundinterface += set_member_value_help_members(q, interface, property, value);
8050  queue_unref(q);
8051  }
8052  }
8053 
8054  if (foundinterface) {
8055  return RESULT_SUCCESS;
8056  } else if (!foundqueue) {
8057  ast_log (LOG_ERROR, "Invalid queuename\n");
8058  } else {
8059  ast_log (LOG_ERROR, "Invalid interface\n");
8060  }
8061 
8062  return RESULT_FAILURE;
8063 }
8064 
8065 /*!
8066  * \brief Gets members penalty.
8067  * \return Return the members penalty or RESULT_FAILURE on error.
8068  */
8069 static int get_member_penalty(char *queuename, char *interface)
8070 {
8071  int foundqueue = 0, penalty;
8072  struct call_queue *q;
8073  struct member *mem;
8074 
8075  if ((q = find_load_queue_rt_friendly(queuename))) {
8076  foundqueue = 1;
8077  ao2_lock(q);
8078  if ((mem = interface_exists(q, interface))) {
8079  penalty = mem->penalty;
8080  ao2_ref(mem, -1);
8081  ao2_unlock(q);
8082  queue_t_unref(q, "Search complete");
8083  return penalty;
8084  }
8085  ao2_unlock(q);
8086  queue_t_unref(q, "Search complete");
8087  }
8088 
8089  /* some useful debugging */
8090  if (foundqueue) {
8091  ast_log (LOG_ERROR, "Invalid queuename\n");
8092  } else {
8093  ast_log (LOG_ERROR, "Invalid interface\n");
8094  }
8095 
8096  return RESULT_FAILURE;
8097 }
8098 
8099 /*! \brief Reload dynamic queue members persisted into the astdb */
8100 static void reload_queue_members(void)
8101 {
8102  char *cur_ptr;
8103  const char *queue_name;
8104  char *member;
8105  char *interface;
8106  char *membername = NULL;
8107  char *state_interface;
8108  char *penalty_tok;
8109  int penalty = 0;
8110  char *paused_tok;
8111  int paused = 0;
8112  char *wrapuptime_tok;
8113  int wrapuptime = 0;
8114  char *reason_paused;
8115  struct ast_db_entry *db_tree;
8116  struct ast_db_entry *entry;
8117  struct call_queue *cur_queue;
8118  char *queue_data;
8119 
8120  /* Each key in 'pm_family' is the name of a queue */
8121  db_tree = ast_db_gettree(pm_family, NULL);
8122  for (entry = db_tree; entry; entry = entry->next) {
8123 
8124  queue_name = entry->key + strlen(pm_family) + 2;
8125 
8126  {
8127  struct call_queue tmpq = {
8128  .name = queue_name,
8129  };
8130  cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members");
8131  }
8132 
8133  if (!cur_queue) {
8134  cur_queue = find_load_queue_rt_friendly(queue_name);
8135  }
8136 
8137  if (!cur_queue) {
8138  /* If the queue no longer exists, remove it from the
8139  * database */
8140  ast_log(LOG_WARNING, "Error loading persistent queue: '%s': it does not exist\n", queue_name);
8141  ast_db_del(pm_family, queue_name);
8142  continue;
8143  }
8144 
8145  if (ast_db_get_allocated(pm_family, queue_name, &queue_data)) {
8146  queue_t_unref(cur_queue, "Expire reload reference");
8147  continue;
8148  }
8149 
8150  cur_ptr = queue_data;
8151  while ((member = strsep(&cur_ptr, ",|"))) {
8152  if (ast_strlen_zero(member)) {
8153  continue;
8154  }
8155 
8156  interface = strsep(&member, ";");
8157  penalty_tok = strsep(&member, ";");
8158  paused_tok = strsep(&member, ";");
8159  membername = strsep(&member, ";");
8160  state_interface = strsep(&member, ";");
8161  reason_paused = strsep(&member, ";");
8162  wrapuptime_tok = strsep(&member, ";");
8163 
8164  if (!penalty_tok) {
8165  ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
8166  break;
8167  }
8168  penalty = strtol(penalty_tok, NULL, 10);
8169  if (errno == ERANGE) {
8170  ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
8171  break;
8172  }
8173 
8174  if (!paused_tok) {
8175  ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
8176  break;
8177  }
8178  paused = strtol(paused_tok, NULL, 10);
8179  if ((errno == ERANGE) || paused < 0 || paused > 1) {
8180  ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
8181  break;
8182  }
8183 
8184  if (!ast_strlen_zero(wrapuptime_tok)) {
8185  wrapuptime = strtol(wrapuptime_tok, NULL, 10);
8186  if (errno == ERANGE) {
8187  ast_log(LOG_WARNING, "Error converting wrapuptime: %s: Out of range.\n", wrapuptime_tok);
8188  break;
8189  }
8190  }
8191 
8192  ast_debug(1, "Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d ReasonPause: %s Wrapuptime: %d\n",
8193  queue_name, interface, membername, penalty, paused, reason_paused, wrapuptime);
8194 
8195  if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface, reason_paused, wrapuptime) == RES_OUTOFMEMORY) {
8196  ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
8197  break;
8198  }
8199  }
8200  queue_t_unref(cur_queue, "Expire reload reference");
8201  ast_free(queue_data);
8202  }
8203 
8204  if (db_tree) {
8205  ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
8206  ast_db_freetree(db_tree);
8207  }
8208 }
8209 
8210 /*! \brief PauseQueueMember application */
8211 static int pqm_exec(struct ast_channel *chan, const char *data)
8212 {
8213  char *parse;
8214  AST_DECLARE_APP_ARGS(args,
8215  AST_APP_ARG(queuename);
8216  AST_APP_ARG(interface);
8217  AST_APP_ARG(options);
8218  AST_APP_ARG(reason);
8219  );
8220 
8221  if (ast_strlen_zero(data)) {
8222  ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
8223  return -1;
8224  }
8225 
8226  parse = ast_strdupa(data);
8227 
8228  AST_STANDARD_APP_ARGS(args, parse);
8229 
8230  if (ast_strlen_zero(args.interface)) {
8231  ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
8232  return -1;
8233  }
8234 
8235  if (set_member_paused(args.queuename, args.interface, args.reason, 1)) {
8236  ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
8237  pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
8238  return 0;
8239  }
8240 
8241  pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED");
8242 
8243  return 0;
8244 }
8245 
8246 /*! \brief UnpauseQueueMember application */
8247 static int upqm_exec(struct ast_channel *chan, const char *data)
8248 {
8249  char *parse;
8250  AST_DECLARE_APP_ARGS(args,
8251  AST_APP_ARG(queuename);
8252  AST_APP_ARG(interface);
8253  AST_APP_ARG(options);
8254  AST_APP_ARG(reason);
8255  );
8256 
8257  if (ast_strlen_zero(data)) {
8258  ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
8259  return -1;
8260  }
8261 
8262  parse = ast_strdupa(data);
8263 
8264  AST_STANDARD_APP_ARGS(args, parse);
8265 
8266  if (ast_strlen_zero(args.interface)) {
8267  ast_log(LOG_WARNING, "Missing interface argument to UnpauseQueueMember ([queuename],interface[,options[,reason]])\n");
8268  return -1;
8269  }
8270 
8271  if (set_member_paused(args.queuename, args.interface, args.reason, 0)) {
8272  ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
8273  pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
8274  return 0;
8275  }
8276 
8277  pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED");
8278 
8279  return 0;
8280 }
8281 
8282 /*! \brief RemoveQueueMember application */
8283 static int rqm_exec(struct ast_channel *chan, const char *data)
8284 {
8285  int res=-1;
8286  char *parse, *temppos = NULL;
8287  struct member *mem = NULL;
8288 
8289  AST_DECLARE_APP_ARGS(args,
8290  AST_APP_ARG(queuename);
8291  AST_APP_ARG(interface);
8292  );
8293 
8294 
8295  if (ast_strlen_zero(data)) {
8296  ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[,interface])\n");
8297  return -1;
8298  }
8299 
8300  parse = ast_strdupa(data);
8301 
8302  AST_STANDARD_APP_ARGS(args, parse);
8303 
8304  if (ast_strlen_zero(args.interface)) {
8305  args.interface = ast_strdupa(ast_channel_name(chan));
8306  temppos = strrchr(args.interface, '-');
8307  if (temppos) {
8308  *temppos = '\0';
8309  }
8310  }
8311 
8312  ast_debug(1, "queue: %s, member: %s\n", args.queuename, args.interface);
8313 
8314  if (log_membername_as_agent) {
8315  mem = find_member_by_queuename_and_interface(args.queuename, args.interface);
8316  }
8317 
8318  switch (remove_from_queue(args.queuename, args.interface)) {
8319  case RES_OKAY:
8320  if (!mem || ast_strlen_zero(mem->membername)) {
8321  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "REMOVEMEMBER", "%s", "");
8322  } else {
8323  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), mem->membername, "REMOVEMEMBER", "%s", "");
8324  }
8325  ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
8326  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
8327  res = 0;
8328  break;
8329  case RES_EXISTS:
8330  ast_debug(1, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
8331  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
8332  res = 0;
8333  break;
8334  case RES_NOSUCHQUEUE:
8335  ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename);
8336  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE");
8337  res = 0;
8338  break;
8339  case RES_NOT_DYNAMIC:
8340  ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': '%s' is not a dynamic member\n", args.queuename, args.interface);
8341  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTDYNAMIC");
8342  res = 0;
8343  break;
8344  }
8345 
8346  if (mem) {
8347  ao2_ref(mem, -1);
8348  }
8349 
8350  return res;
8351 }
8352 
8353 /*! \brief AddQueueMember application */
8354 static int aqm_exec(struct ast_channel *chan, const char *data)
8355 {
8356  int res=-1;
8357  char *parse, *tmp, *temppos = NULL;
8358  AST_DECLARE_APP_ARGS(args,
8359  AST_APP_ARG(queuename);
8360  AST_APP_ARG(interface);
8361  AST_APP_ARG(penalty);
8362  AST_APP_ARG(options);
8365  AST_APP_ARG(wrapuptime);
8366  );
8367  int penalty = 0;
8368  int wrapuptime;
8369 
8370  if (ast_strlen_zero(data)) {
8371  ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface][,wrapuptime]]]]])\n");
8372  return -1;
8373  }
8374 
8375  parse = ast_strdupa(data);
8376 
8377  AST_STANDARD_APP_ARGS(args, parse);
8378 
8379  if (ast_strlen_zero(args.interface)) {
8380  args.interface = ast_strdupa(ast_channel_name(chan));
8381  temppos = strrchr(args.interface, '-');
8382  if (temppos) {
8383  *temppos = '\0';
8384  }
8385  }
8386 
8387  if (!ast_strlen_zero(args.penalty)) {
8388  if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
8389  ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
8390  penalty = 0;
8391  }
8392  }
8393 
8394  if (!ast_strlen_zero(args.wrapuptime)) {
8395  tmp = args.wrapuptime;
8396  ast_strip(tmp);
8397  wrapuptime = atoi(tmp);
8398  if (wrapuptime < 0) {
8399  wrapuptime = 0;
8400  }
8401  } else {
8402  wrapuptime = 0;
8403  }
8404 
8405  switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL, wrapuptime)) {
8406  case RES_OKAY:
8407  if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
8408  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
8409  } else {
8410  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.membername, "ADDMEMBER", "%s", "");
8411  }
8412  ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
8413  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
8414  res = 0;
8415  break;
8416  case RES_EXISTS:
8417  ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
8418  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
8419  res = 0;
8420  break;
8421  case RES_NOSUCHQUEUE:
8422  ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
8423  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
8424  res = 0;
8425  break;
8426  case RES_OUTOFMEMORY:
8427  ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
8428  break;
8429  }
8430 
8431  return res;
8432 }
8433 
8434 /*! \brief QueueLog application */
8435 static int ql_exec(struct ast_channel *chan, const char *data)
8436 {
8437  char *parse;
8438 
8439  AST_DECLARE_APP_ARGS(args,
8440  AST_APP_ARG(queuename);
8441  AST_APP_ARG(uniqueid);
8443  AST_APP_ARG(event);
8444  AST_APP_ARG(params);
8445  );
8446 
8447  if (ast_strlen_zero(data)) {
8448  ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo]\n");
8449  return -1;
8450  }
8451 
8452  parse = ast_strdupa(data);
8453 
8454  AST_STANDARD_APP_ARGS(args, parse);
8455 
8456  if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid)
8457  || ast_strlen_zero(args.membername) || ast_strlen_zero(args.event)) {
8458  ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo])\n");
8459  return -1;
8460  }
8461 
8462  ast_queue_log(args.queuename, args.uniqueid, args.membername, args.event,
8463  "%s", args.params ? args.params : "");
8464 
8465  return 0;
8466 }
8467 
8468 /*! \brief Copy rule from global list into specified queue */
8469 static void copy_rules(struct queue_ent *qe, const char *rulename)
8470 {
8471  struct penalty_rule *pr_iter;
8472  struct rule_list *rl_iter;
8473  const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
8475  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
8476  if (!strcasecmp(rl_iter->name, tmp)) {
8477  break;
8478  }
8479  }
8480  if (rl_iter) {
8481  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
8482  struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
8483  if (!new_pr) {
8484  ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
8485  break;
8486  }
8487  new_pr->time = pr_iter->time;
8488  new_pr->max_value = pr_iter->max_value;
8489  new_pr->min_value = pr_iter->min_value;
8490  new_pr->raise_value = pr_iter->raise_value;
8491  new_pr->max_relative = pr_iter->max_relative;
8492  new_pr->min_relative = pr_iter->min_relative;
8493  new_pr->raise_relative = pr_iter->raise_relative;
8494  AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
8495  }
8496  }
8498 }
8499 
8500 /*!\brief The starting point for all queue calls
8501  *
8502  * The process involved here is to
8503  * 1. Parse the options specified in the call to Queue()
8504  * 2. Join the queue
8505  * 3. Wait in a loop until it is our turn to try calling a queue member
8506  * 4. Attempt to call a queue member
8507  * 5. If 4. did not result in a bridged call, then check for between
8508  * call options such as periodic announcements etc.
8509  * 6. Try 4 again unless some condition (such as an expiration time) causes us to
8510  * exit the queue.
8511  */
8512 static int queue_exec(struct ast_channel *chan, const char *data)
8513 {
8514  int res=-1;
8515  int ringing=0;
8516  const char *user_priority;
8517  const char *max_penalty_str;
8518  const char *min_penalty_str;
8519  const char *raise_penalty_str;
8520  int prio;
8521  int qcontinue = 0;
8523  enum queue_result reason = QUEUE_UNKNOWN;
8524  /* whether to exit Queue application after the timeout hits */
8525  int tries = 0;
8526  int noption = 0;
8527  char *parse;
8528  int makeannouncement = 0;
8529  int position = 0;
8530  AST_DECLARE_APP_ARGS(args,
8531  AST_APP_ARG(queuename);
8532  AST_APP_ARG(options);
8533  AST_APP_ARG(url);
8534  AST_APP_ARG(announceoverride);
8535  AST_APP_ARG(queuetimeoutstr);
8536  AST_APP_ARG(agi);
8537  AST_APP_ARG(gosub);
8538  AST_APP_ARG(rule);
8539  AST_APP_ARG(position);
8540  );
8541  /* Our queue entry */
8542  struct queue_ent qe = { 0 };
8543  struct ast_flags opts = { 0, };
8544  char *opt_args[OPT_ARG_ARRAY_SIZE];
8545  int max_forwards;
8546  int cid_allow;
8547 
8548  if (ast_strlen_zero(data)) {
8549  ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,gosub[,rule[,position]]]]]]]]\n");
8550  return -1;
8551  }
8552 
8553  ast_channel_lock(chan);
8554  max_forwards = ast_max_forwards_get(chan);
8555  ast_channel_unlock(chan);
8556 
8557  if (max_forwards <= 0) {
8558  ast_log(LOG_WARNING, "Channel '%s' cannot enter queue. Max forwards exceeded\n", ast_channel_name(chan));
8559  return -1;
8560  }
8561 
8562  parse = ast_strdupa(data);
8563  AST_STANDARD_APP_ARGS(args, parse);
8564 
8565  ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, timeout: %s, agi: %s, gosub: %s, rule: %s, position: %s\n",
8566  args.queuename,
8567  S_OR(args.options, ""),
8568  S_OR(args.url, ""),
8569  S_OR(args.announceoverride, ""),
8570  S_OR(args.queuetimeoutstr, ""),
8571  S_OR(args.agi, ""),
8572  S_OR(args.gosub, ""),
8573  S_OR(args.rule, ""),
8574  S_OR(args.position, ""));
8575 
8576  if (!ast_strlen_zero(args.options)) {
8577  ast_app_parse_options(queue_exec_options, &opts, opt_args, args.options);
8578  }
8579 
8580  /* Setup our queue entry */
8581  qe.start = time(NULL);
8582 
8583  pbx_builtin_setvar_helper(chan, "ABANDONED", NULL);
8584 
8585  /* set the expire time based on the supplied timeout; */
8586  if (!ast_strlen_zero(args.queuetimeoutstr)) {
8587  qe.expire = qe.start + atoi(args.queuetimeoutstr);
8588  } else {
8589  qe.expire = 0;
8590  }
8591 
8592  /* Get the priority from the variable ${QUEUE_PRIO} */
8593  ast_channel_lock(chan);
8594  user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
8595  if (user_priority) {
8596  if (sscanf(user_priority, "%30d", &prio) == 1) {
8597  ast_debug(1, "%s: Got priority %d from ${QUEUE_PRIO}.\n", ast_channel_name(chan), prio);
8598  } else {
8599  ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
8600  user_priority, ast_channel_name(chan));
8601  prio = 0;
8602  }
8603  } else {
8604  ast_debug(3, "NO QUEUE_PRIO variable found. Using default.\n");
8605  prio = 0;
8606  }
8607 
8608  /* Get the maximum penalty from the variable ${QUEUE_MAX_PENALTY} */
8609 
8610  if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
8611  if (sscanf(max_penalty_str, "%30d", &max_penalty) == 1) {
8612  ast_debug(1, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", ast_channel_name(chan), max_penalty);
8613  } else {
8614  ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
8615  max_penalty_str, ast_channel_name(chan));
8616  max_penalty = INT_MAX;
8617  }
8618  } else {
8619  max_penalty = INT_MAX;
8620  }
8621 
8622  if ((min_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MIN_PENALTY"))) {
8623  if (sscanf(min_penalty_str, "%30d", &min_penalty) == 1) {
8624  ast_debug(1, "%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", ast_channel_name(chan), min_penalty);
8625  } else {
8626  ast_log(LOG_WARNING, "${QUEUE_MIN_PENALTY}: Invalid value (%s), channel %s.\n",
8627  min_penalty_str, ast_channel_name(chan));
8628  min_penalty = INT_MAX;
8629  }
8630  } else {
8631  min_penalty = INT_MAX;
8632  }
8633 
8634  if ((raise_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_RAISE_PENALTY"))) {
8635  if (sscanf(raise_penalty_str, "%30d", &raise_penalty) == 1) {
8636  ast_debug(1, "%s: Got raise penalty %d from ${QUEUE_RAISE_PENALTY}.\n", ast_channel_name(chan), raise_penalty);
8637  } else {
8638  ast_log(LOG_WARNING, "${QUEUE_RAISE_PENALTY}: Invalid value (%s), channel %s.\n",
8639  raise_penalty_str, ast_channel_name(chan));
8640  raise_penalty = INT_MAX;
8641  }
8642  } else {
8643  raise_penalty = INT_MAX;
8644  }
8645  ast_channel_unlock(chan);
8646 
8647  if (ast_test_flag(&opts, OPT_RINGING)) {
8648  ringing = 1;
8649  }
8650 
8651  if (ringing != 1 && ast_test_flag(&opts, OPT_RING_WHEN_RINGING)) {
8652  qe.ring_when_ringing = 1;
8653  }
8654 
8655  if (ast_test_flag(&opts, OPT_GO_ON)) {
8656  qcontinue = 1;
8657  }
8658 
8659  if (args.position) {
8660  position = atoi(args.position);
8661  if (position < 0) {
8662  ast_log(LOG_WARNING, "Invalid position '%s' given for call to queue '%s'. Assuming no preference for position\n", args.position, args.queuename);
8663  position = 0;
8664  }
8665  }
8666 
8667  ast_debug(1, "queue: %s, expires: %ld, priority: %d\n",
8668  args.queuename, (long)qe.expire, prio);
8669 
8670  qe.chan = chan;
8671  qe.prio = prio;
8672  qe.max_penalty = max_penalty;
8673  qe.min_penalty = min_penalty;
8675  qe.last_pos_said = 0;
8676  qe.last_pos = 0;
8677  qe.last_periodic_announce_time = time(NULL);
8679  qe.valid_digits = 0;
8680  if (join_queue(args.queuename, &qe, &reason, position)) {
8681  ast_log(LOG_WARNING, "Unable to join queue '%s'\n", args.queuename);
8682  set_queue_result(chan, reason);
8683  return 0;
8684  }
8685  ast_assert(qe.parent != NULL);
8686 
8687  if (qe.parent->periodicannouncestartdelay >= 0) {
8690  }
8691 
8692  cid_allow = qe.parent->log_restricted_caller_id || ((ast_party_id_presentation(&ast_channel_caller(chan)->id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED);
8693 
8694  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ENTERQUEUE", "%s|%s|%d",
8695  S_OR(args.url, ""),
8696  S_COR(cid_allow && ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
8697  qe.opos);
8698 
8699  /* PREDIAL: Preprocess any callee gosub arguments. */
8700  if (ast_test_flag(&opts, OPT_PREDIAL_CALLEE)
8701  && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLEE])) {
8702  ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLEE]);
8703  qe.predial_callee = opt_args[OPT_ARG_PREDIAL_CALLEE];
8704  }
8705 
8706  /* PREDIAL: Run gosub on the caller's channel */
8707  if (ast_test_flag(&opts, OPT_PREDIAL_CALLER)
8708  && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLER])) {
8709  ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLER]);
8710  ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0);
8711  }
8712 
8713  /* Music on hold class override */
8714  if (ast_test_flag(&opts, OPT_MUSICONHOLD_CLASS)
8715  && !ast_strlen_zero(opt_args[OPT_ARG_MUSICONHOLD_CLASS])) {
8716  ast_copy_string(qe.moh, opt_args[OPT_ARG_MUSICONHOLD_CLASS], sizeof(qe.moh));
8717  }
8718 
8719  copy_rules(&qe, args.rule);
8720  qe.pr = AST_LIST_FIRST(&qe.qe_rules);
8721 check_turns:
8722  if (ringing) {
8724  } else {
8725  ast_moh_start(chan, qe.moh, NULL);
8726  }
8727 
8728  /* This is the wait loop for callers 2 through maxlen */
8729  res = wait_our_turn(&qe, ringing, &reason);
8730  if (res) {
8731  goto stop;
8732  }
8733 
8734  makeannouncement = qe.parent->announce_to_first_user;
8735 
8736  for (;;) {
8737  /* This is the wait loop for the head caller*/
8738  /* To exit, they may get their call answered; */
8739  /* they may dial a digit from the queue context; */
8740  /* or, they may timeout. */
8741 
8742  /* A request to withdraw this call from the queue arrived */
8743  if (qe.withdraw) {
8744  reason = QUEUE_WITHDRAW;
8745  res = 1;
8746  break;
8747  }
8748 
8749  /* Leave if we have exceeded our queuetimeout */
8750  if (qe.expire && (time(NULL) >= qe.expire)) {
8751  record_abandoned(&qe);
8752  reason = QUEUE_TIMEOUT;
8753  res = 0;
8754  ast_queue_log(args.queuename, ast_channel_uniqueid(chan),"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
8755  qe.pos, qe.opos, (long) (time(NULL) - qe.start));
8756  break;
8757  }
8758 
8759  if (makeannouncement) {
8760  /* Make a position announcement, if enabled */
8761  if (qe.parent->announcefrequency) {
8762  if ((res = say_position(&qe, ringing))) {
8763  goto stop;
8764  }
8765  }
8766  }
8767  makeannouncement = 1;
8768 
8769  /* Make a periodic announcement, if enabled */
8771  if ((res = say_periodic_announcement(&qe, ringing))) {
8772  goto stop;
8773  }
8774  }
8775 
8776  /* A request to withdraw this call from the queue arrived */
8777  if (qe.withdraw) {
8778  reason = QUEUE_WITHDRAW;
8779  res = 1;
8780  break;
8781  }
8782 
8783  /* Leave if we have exceeded our queuetimeout */
8784  if (qe.expire && (time(NULL) >= qe.expire)) {
8785  record_abandoned(&qe);
8786  reason = QUEUE_TIMEOUT;
8787  res = 0;
8788  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHTIMEOUT",
8789  "%d|%d|%ld", qe.pos, qe.opos, (long) (time(NULL) - qe.start));
8790  break;
8791  }
8792 
8793  /* see if we need to move to the next penalty level for this queue */
8794  while (qe.pr && ((time(NULL) - qe.start) > qe.pr->time)) {
8795  update_qe_rule(&qe);
8796  }
8797 
8798  /* Try calling all queue members for 'timeout' seconds */
8799  res = try_calling(&qe, opts, opt_args, args.announceoverride, args.url, &tries, &noption, args.agi, args.gosub, ringing);
8800  if (res) {
8801  goto stop;
8802  }
8803 
8804  if (qe.parent->leavewhenempty) {
8805  int status = 0;
8806  if ((status = get_member_status(qe.parent, qe.max_penalty, qe.min_penalty, qe.raise_penalty, qe.parent->leavewhenempty, 0))) {
8807  record_abandoned(&qe);
8808  reason = QUEUE_LEAVEEMPTY;
8809  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe.pos, qe.opos, (long)(time(NULL) - qe.start));
8810  res = 0;
8811  break;
8812  }
8813  }
8814 
8815  /* exit after 'timeout' cycle if 'n' option enabled */
8816  if (noption && tries >= ao2_container_count(qe.parent->members)) {
8817  ast_verb(3, "Exiting on time-out cycle\n");
8818  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHTIMEOUT",
8819  "%d|%d|%ld", qe.pos, qe.opos, (long) (time(NULL) - qe.start));
8820  record_abandoned(&qe);
8821  reason = QUEUE_TIMEOUT;
8822  res = 0;
8823  break;
8824  }
8825 
8826 
8827  /* Leave if we have exceeded our queuetimeout */
8828  if (qe.expire && (time(NULL) >= qe.expire)) {
8829  record_abandoned(&qe);
8830  reason = QUEUE_TIMEOUT;
8831  res = 0;
8832  ast_queue_log(qe.parent->name, ast_channel_uniqueid(qe.chan),"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld", qe.pos, qe.opos, (long) (time(NULL) - qe.start));
8833  break;
8834  }
8835 
8836  /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
8837  res = wait_a_bit(&qe);
8838  if (res) {
8839  goto stop;
8840  }
8841 
8842  /* If using dynamic realtime members, we should regenerate the member list for this queue */
8843  update_realtime_members(qe.parent);
8844 
8845  /* Since this is a priority queue and
8846  * it is not sure that we are still at the head
8847  * of the queue, go and check for our turn again.
8848  */
8849  if (!is_our_turn(&qe)) {
8850  ast_debug(1, "Darn priorities, going back in queue (%s)!\n", ast_channel_name(qe.chan));
8851  goto check_turns;
8852  }
8853  }
8854 
8855 stop:
8856  if (res) {
8857  if (reason == QUEUE_WITHDRAW) {
8858  record_abandoned(&qe);
8859  ast_queue_log(qe.parent->name, ast_channel_uniqueid(qe.chan), "NONE", "WITHDRAW", "%d|%d|%ld|%.40s", qe.pos, qe.opos, (long) (time(NULL) - qe.start), qe.withdraw_info ? qe.withdraw_info : "");
8860  if (qe.withdraw_info) {
8861  pbx_builtin_setvar_helper(qe.chan, "QUEUE_WITHDRAW_INFO", qe.withdraw_info);
8862  }
8863  res = 0;
8864  } else if (res < 0) {
8865  if (!qe.handled) {
8866  record_abandoned(&qe);
8867  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ABANDON",
8868  "%d|%d|%ld", qe.pos, qe.opos,
8869  (long) (time(NULL) - qe.start));
8870  res = -1;
8871  } else if (reason == QUEUE_LEAVEEMPTY) {
8872  /* Return back to dialplan, don't hang up */
8873  res = 0;
8874  } else if (qcontinue) {
8875  reason = QUEUE_CONTINUE;
8876  res = 0;
8877  }
8878  } else if (qe.valid_digits) {
8879  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHKEY",
8880  "%s|%d|%d|%ld", qe.digits, qe.pos, qe.opos, (long) (time(NULL) - qe.start));
8881  }
8882  }
8883 
8884  /* Free the optional withdraw info if present */
8885  /* This is done here to catch all cases. e.g. if the call eventually wasn't withdrawn, e.g. answered */
8886  if (qe.withdraw_info) {
8887  ast_free(qe.withdraw_info);
8888  qe.withdraw_info = NULL;
8889  }
8890 
8891  /* Don't allow return code > 0 */
8892  if (res >= 0) {
8893  res = 0;
8894  if (ringing) {
8895  ast_indicate(chan, -1);
8896  } else {
8897  ast_moh_stop(chan);
8898  }
8899  ast_stopstream(chan);
8900  }
8901 
8903 
8904  leave_queue(&qe);
8905  if (reason != QUEUE_UNKNOWN)
8906  set_queue_result(chan, reason);
8907 
8908  /*
8909  * every queue_ent is given a reference to it's parent
8910  * call_queue when it joins the queue. This ref must be taken
8911  * away right before the queue_ent is destroyed. In this case
8912  * the queue_ent is about to be returned on the stack
8913  */
8914  qe.parent = queue_unref(qe.parent);
8915 
8916  return res;
8917 }
8918 
8919 /*!
8920  * \brief create interface var with all queue details.
8921  * \retval 0 on success
8922  * \retval -1 on error
8923 */
8924 static int queue_function_var(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
8925 {
8926  int res = -1;
8927  struct call_queue *q;
8928  char interfacevar[256] = "";
8929  float sl = 0;
8930 
8931  if (ast_strlen_zero(data)) {
8932  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
8933  return -1;
8934  }
8935 
8936  if ((q = find_load_queue_rt_friendly(data))) {
8937  ao2_lock(q);
8938  if (q->setqueuevar) {
8939  sl = 0;
8940  res = 0;
8941 
8942  if (q->callscompleted > 0) {
8943  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
8944  }
8945 
8946  snprintf(interfacevar, sizeof(interfacevar),
8947  "QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
8948  q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
8949 
8950  pbx_builtin_setvar_multiple(chan, interfacevar);
8951  }
8952 
8953  ao2_unlock(q);
8954  queue_t_unref(q, "Done with QUEUE() function");
8955  } else {
8956  ast_log(LOG_WARNING, "queue %s was not found\n", data);
8957  }
8958 
8959  snprintf(buf, len, "%d", res);
8960 
8961  return 0;
8962 }
8963 
8964 /*!
8965  * \brief Check if a given queue exists
8966  *
8967  */
8968 static int queue_function_exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
8969 {
8970  struct call_queue *q;
8971 
8972  buf[0] = '\0';
8973 
8974  if (ast_strlen_zero(data)) {
8975  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
8976  return -1;
8977  }
8978  q = find_load_queue_rt_friendly(data);
8979  snprintf(buf, len, "%d", q != NULL? 1 : 0);
8980  if (q) {
8981  queue_t_unref(q, "Done with temporary reference in QUEUE_EXISTS()");
8982  }
8983 
8984  return 0;
8985 }
8986 
8987 static struct member *get_interface_helper(struct call_queue *q, const char *interface)
8988 {
8989  struct member *m;
8990 
8991  if (ast_strlen_zero(interface)) {
8992  ast_log(LOG_ERROR, "QUEUE_MEMBER: Missing required interface argument.\n");
8993  return NULL;
8994  }
8995 
8996  m = interface_exists(q, interface);
8997  if (!m) {
8998  ast_log(LOG_ERROR, "Queue member interface '%s' not in queue '%s'.\n",
8999  interface, q->name);
9000  }
9001  return m;
9002 }
9003 
9004 /*!
9005  * \brief Get number either busy / free / ready or total members of a specific queue
9006  * \brief Get or set member properties penalty / paused / ringinuse
9007  * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ringinuse)
9008  * \retval -1 on error
9009  */
9010 static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
9011 {
9012  int count = 0;
9013  struct member *m;
9014  struct ao2_iterator mem_iter;
9015  struct call_queue *q;
9016 
9017  AST_DECLARE_APP_ARGS(args,
9018  AST_APP_ARG(queuename);
9019  AST_APP_ARG(option);
9020  AST_APP_ARG(interface);
9021  );
9022  /* Make sure the returned value on error is zero length string. */
9023  buf[0] = '\0';
9024 
9025  if (ast_strlen_zero(data)) {
9026  ast_log(LOG_ERROR,
9027  "Missing required argument. %s(<queuename>,<option>[,<interface>])\n",
9028  cmd);
9029  return -1;
9030  }
9031 
9032  AST_STANDARD_APP_ARGS(args, data);
9033 
9034  if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.option)) {
9035  ast_log(LOG_ERROR,
9036  "Missing required argument. %s(<queuename>,<option>[,<interface>])\n",
9037  cmd);
9038  return -1;
9039  }
9040 
9041  if ((q = find_load_queue_rt_friendly(args.queuename))) {
9042  ao2_lock(q);
9043  if (!strcasecmp(args.option, "logged")) {
9044  mem_iter = ao2_iterator_init(q->members, 0);
9045  while ((m = ao2_iterator_next(&mem_iter))) {
9046  /* Count the agents who are logged in and presently answering calls */
9047  if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
9048  count++;
9049  }
9050  ao2_ref(m, -1);
9051  }
9052  ao2_iterator_destroy(&mem_iter);
9053  } else if (!strcasecmp(args.option, "free")) {
9054  mem_iter = ao2_iterator_init(q->members, 0);
9055  while ((m = ao2_iterator_next(&mem_iter))) {
9056  /* Count the agents who are logged in and presently answering calls */
9057  if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused)) {
9058  count++;
9059  }
9060  ao2_ref(m, -1);
9061  }
9062  ao2_iterator_destroy(&mem_iter);
9063  } else if (!strcasecmp(args.option, "ready")) {
9064  time_t now;
9065  time(&now);
9066  mem_iter = ao2_iterator_init(q->members, 0);
9067  while ((m = ao2_iterator_next(&mem_iter))) {
9068  /* Count the agents who are logged in, not paused and not wrapping up */
9069  if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused) &&
9070  !(m->lastcall && get_wrapuptime(q, m) && ((now - get_wrapuptime(q, m)) < m->lastcall))) {
9071  count++;
9072  }
9073  ao2_ref(m, -1);
9074  }
9075  ao2_iterator_destroy(&mem_iter);
9076  } else if (!strcasecmp(args.option, "count")) {
9077  count = ao2_container_count(q->members);
9078  } else if (!strcasecmp(args.option, "penalty")) {
9079  m = get_interface_helper(q, args.interface);
9080  if (m) {
9081  count = m->penalty;
9082  ao2_ref(m, -1);
9083  }
9084  } else if (!strcasecmp(args.option, "paused")) {
9085  m = get_interface_helper(q, args.interface);
9086  if (m) {
9087  count = m->paused;
9088  ao2_ref(m, -1);
9089  }
9090  } else if ((!strcasecmp(args.option, "ignorebusy") /* ignorebusy is legacy */
9091  || !strcasecmp(args.option, "ringinuse"))) {
9092  m = get_interface_helper(q, args.interface);
9093  if (m) {
9094  count = m->ringinuse;
9095  ao2_ref(m, -1);
9096  }
9097  } else {
9098  ast_log(LOG_ERROR, "%s: Invalid option '%s' provided.\n", cmd, args.option);
9099  }
9100  ao2_unlock(q);
9101  queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
9102  } else {
9103  ast_log(LOG_WARNING, "queue %s was not found\n", args.queuename);
9104  }
9105 
9106  snprintf(buf, len, "%d", count);
9107 
9108  return 0;
9109 }
9110 
9111 /*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ringinuse. */
9112 static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
9113 {
9114  int memvalue;
9115 
9116  AST_DECLARE_APP_ARGS(args,
9117  AST_APP_ARG(queuename);
9118  AST_APP_ARG(option);
9119  AST_APP_ARG(interface);
9120  );
9121 
9122  if (ast_strlen_zero(data)) {
9123  ast_log(LOG_ERROR,
9124  "Missing required argument. %s([<queuename>],<option>,<interface>)\n",
9125  cmd);
9126  return -1;
9127  }
9128 
9129  AST_STANDARD_APP_ARGS(args, data);
9130 
9131  if (ast_strlen_zero(args.option)
9132  || ast_strlen_zero(args.interface)) {
9133  ast_log(LOG_ERROR,
9134  "Missing required argument. %s([<queuename>],<option>,<interface>)\n",
9135  cmd);
9136  return -1;
9137  }
9138 
9139  /*
9140  * If queuename is empty then the option will be
9141  * set for the interface in all queues.
9142  */
9143 
9144  memvalue = atoi(value);
9145  if (!strcasecmp(args.option, "penalty")) {
9146  if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, memvalue)) {
9147  ast_log(LOG_ERROR, "Invalid interface, queue, or penalty\n");
9148  return -1;
9149  }
9150  } else if (!strcasecmp(args.option, "paused")) {
9151  memvalue = (memvalue <= 0) ? 0 : 1;
9152  if (set_member_paused(args.queuename, args.interface, NULL, memvalue)) {
9153  ast_log(LOG_ERROR, "Invalid interface or queue\n");
9154  return -1;
9155  }
9156  } else if (!strcasecmp(args.option, "ignorebusy") /* ignorebusy is legacy */
9157  || !strcasecmp(args.option, "ringinuse")) {
9158  memvalue = (memvalue <= 0) ? 0 : 1;
9159  if (set_member_value(args.queuename, args.interface, MEMBER_RINGINUSE, memvalue)) {
9160  ast_log(LOG_ERROR, "Invalid interface or queue\n");
9161  return -1;
9162  }
9163  } else {
9164  ast_log(LOG_ERROR, "%s: Invalid option '%s' provided.\n", cmd, args.option);
9165  return -1;
9166  }
9167  return 0;
9168 }
9169 
9170 /*!
9171  * \brief Get the total number of members in a specific queue (Deprecated)
9172  * \retval number of members
9173  * \retval -1 on error
9174 */
9175 static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
9176 {
9177  int count = 0;
9178  struct member *m;
9179  struct call_queue *q;
9180  struct ao2_iterator mem_iter;
9181  static int depflag = 1;
9182 
9183  if (depflag) {
9184  depflag = 0;
9185  ast_log(LOG_NOTICE, "The function QUEUE_MEMBER_COUNT has been deprecated in favor of the QUEUE_MEMBER function and will not be in further releases.\n");
9186  }
9187 
9188  if (ast_strlen_zero(data)) {
9189  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
9190  return -1;
9191  }
9192 
9193  if ((q = find_load_queue_rt_friendly(data))) {
9194  ao2_lock(q);
9195  mem_iter = ao2_iterator_init(q->members, 0);
9196  while ((m = ao2_iterator_next(&mem_iter))) {
9197  /* Count the agents who are logged in and presently answering calls */
9198  if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
9199  count++;
9200  }
9201  ao2_ref(m, -1);
9202  }
9203  ao2_iterator_destroy(&mem_iter);
9204  ao2_unlock(q);
9205  queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER_COUNT");
9206  } else {
9207  ast_log(LOG_WARNING, "queue %s was not found\n", data);
9208  }
9209 
9210  snprintf(buf, len, "%d", count);
9211 
9212  return 0;
9213 }
9214 
9215 /*! \brief Dialplan function QUEUE_GET_CHANNEL() Get caller channel waiting at specified position in the queue */
9216 static int queue_function_queuegetchannel(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
9217 {
9218  int position;
9219  char *parse;
9220  struct call_queue *q;
9221  struct ast_variable *var;
9222 
9223  AST_DECLARE_APP_ARGS(args,
9224  AST_APP_ARG(queuename);
9225  AST_APP_ARG(position);
9226  );
9227 
9228  buf[0] = '\0';
9229 
9230  if (ast_strlen_zero(data)) {
9231  ast_log(LOG_ERROR, "Missing argument. QUEUE_GET_CHANNEL(<queuename>,<position>)\n");
9232  return -1;
9233  }
9234 
9235  parse = ast_strdupa(data);
9236  AST_STANDARD_APP_ARGS(args, parse);
9237 
9238  if (ast_strlen_zero(args.queuename)) {
9239  ast_log (LOG_ERROR, "The <queuename> parameter is required.\n");
9240  return -1;
9241  }
9242 
9243  if (ast_strlen_zero(args.position)) {
9244  position = 1;
9245  } else {
9246  if (sscanf(args.position, "%30d", &position) != 1) {
9247  ast_log (LOG_ERROR, "<position> parameter must be an integer.\n");
9248  return -1;
9249  }
9250  if (position < 1) {
9251  ast_log (LOG_ERROR, "<position> parameter must be an integer greater than zero.\n");
9252  return -1;
9253  }
9254  }
9255 
9256  {
9257  struct call_queue tmpq = {
9258  .name = args.queuename,
9259  };
9260 
9261  q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_GET_CHANNEL()");
9262  }
9263  if (q) {
9264  ao2_lock(q);
9265  if (q->count >= position) {
9266  struct queue_ent *qe;
9267 
9268  for (qe = q->head; qe; qe = qe->next) {
9269  if (qe->pos == position) {
9270  ast_copy_string(buf, ast_channel_name(qe->chan), len);
9271  break;
9272  }
9273  }
9274  }
9275  ao2_unlock(q);
9276  queue_t_unref(q, "Done with reference in QUEUE_GET_CHANNEL()");
9277  return 0;
9278  }
9279 
9280  var = ast_load_realtime("queues", "name", args.queuename, SENTINEL);
9281  if (var) {
9282  /* if the queue is realtime but was not found in memory, this
9283  * means that the queue had been deleted from memory since it was
9284  * "dead."
9285  */
9286  ast_variables_destroy(var);
9287  return 0;
9288  }
9289 
9290  ast_log(LOG_WARNING, "queue %s was not found\n", args.queuename);
9291  return 0;
9292 }
9293 
9294 /*! \brief Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue */
9295 static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
9296 {
9297  int count = 0;
9298  struct call_queue *q, tmpq = {
9299  .name = data,
9300  };
9301  struct ast_variable *var = NULL;
9302 
9303  buf[0] = '\0';
9304 
9305  if (ast_strlen_zero(data)) {
9306  ast_log(LOG_ERROR, "QUEUE_WAITING_COUNT requires an argument: queuename\n");
9307  return -1;
9308  }
9309 
9310  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_WAITING_COUNT()"))) {
9311  ao2_lock(q);
9312  count = q->count;
9313  ao2_unlock(q);
9314  queue_t_unref(q, "Done with reference in QUEUE_WAITING_COUNT()");
9315  } else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) {
9316  /* if the queue is realtime but was not found in memory, this
9317  * means that the queue had been deleted from memory since it was
9318  * "dead." This means it has a 0 waiting count
9319  */
9320  count = 0;
9321  ast_variables_destroy(var);
9322  } else {
9323  ast_log(LOG_WARNING, "queue %s was not found\n", data);
9324  }
9325 
9326  snprintf(buf, len, "%d", count);
9327 
9328  return 0;
9329 }
9330 
9331 /*! \brief Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue */
9332 static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
9333 {
9334  struct call_queue *q;
9335  struct member *m;
9336 
9337  /* Ensure an otherwise empty list doesn't return garbage */
9338  buf[0] = '\0';
9339 
9340  if (ast_strlen_zero(data)) {
9341  ast_log(LOG_ERROR, "QUEUE_MEMBER_LIST requires an argument: queuename\n");
9342  return -1;
9343  }
9344 
9345  if ((q = find_load_queue_rt_friendly(data))) {
9346  int buflen = 0, count = 0;
9347  struct ao2_iterator mem_iter;
9348 
9349  ao2_lock(q);
9350  mem_iter = ao2_iterator_init(q->members, 0);
9351  while ((m = ao2_iterator_next(&mem_iter))) {
9352  /* strcat() is always faster than printf() */
9353  if (count++) {
9354  strncat(buf + buflen, ",", len - buflen - 1);
9355  buflen++;
9356  }
9357  strncat(buf + buflen, m->interface, len - buflen - 1);
9358  buflen += strlen(m->interface);
9359  /* Safeguard against overflow (negative length) */
9360  if (buflen >= len - 2) {
9361  ao2_ref(m, -1);
9362  ast_log(LOG_WARNING, "Truncating list\n");
9363  break;
9364  }
9365  ao2_ref(m, -1);
9366  }
9367  ao2_iterator_destroy(&mem_iter);
9368  ao2_unlock(q);
9369  queue_t_unref(q, "Done with QUEUE_MEMBER_LIST()");
9370  } else
9371  ast_log(LOG_WARNING, "queue %s was not found\n", data);
9372 
9373  /* We should already be terminated, but let's make sure. */
9374  buf[len - 1] = '\0';
9375 
9376  return 0;
9377 }
9378 
9379 /*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty. */
9380 static int queue_function_memberpenalty_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
9381 {
9382  int penalty;
9383  AST_DECLARE_APP_ARGS(args,
9384  AST_APP_ARG(queuename);
9385  AST_APP_ARG(interface);
9386  );
9387  /* Make sure the returned value on error is NULL. */
9388  buf[0] = '\0';
9389 
9390  if (ast_strlen_zero(data)) {
9391  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
9392  return -1;
9393  }
9394 
9395  AST_STANDARD_APP_ARGS(args, data);
9396 
9397  if (args.argc < 2) {
9398  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
9399  return -1;
9400  }
9401 
9402  penalty = get_member_penalty (args.queuename, args.interface);
9403 
9404  if (penalty >= 0) { /* remember that buf is already '\0' */
9405  snprintf (buf, len, "%d", penalty);
9406  }
9407 
9408  return 0;
9409 }
9410 
9411 /*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty. */
9412 static int queue_function_memberpenalty_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
9413 {
9414  int penalty;
9415  AST_DECLARE_APP_ARGS(args,
9416  AST_APP_ARG(queuename);
9417  AST_APP_ARG(interface);
9418  );
9419 
9420  if (ast_strlen_zero(data)) {
9421  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
9422  return -1;
9423  }
9424 
9425  AST_STANDARD_APP_ARGS(args, data);
9426 
9427  if (args.argc < 2) {
9428  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
9429  return -1;
9430  }
9431 
9432  penalty = atoi(value);
9433 
9434  if (ast_strlen_zero(args.interface)) {
9435  ast_log (LOG_ERROR, "<interface> parameter can't be null\n");
9436  return -1;
9437  }
9438 
9439  /* if queuename = NULL then penalty will be set for interface in all the queues. */
9440  if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, penalty)) {
9441  ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
9442  return -1;
9443  }
9444 
9445  return 0;
9446 }
9447 
9448 static struct ast_custom_function queueexists_function = {
9449  .name = "QUEUE_EXISTS",
9450  .read = queue_function_exists,
9451 };
9452 
9453 static struct ast_custom_function queuevar_function = {
9454  .name = "QUEUE_VARIABLES",
9455  .read = queue_function_var,
9456 };
9457 
9458 static struct ast_custom_function queuemembercount_function = {
9459  .name = "QUEUE_MEMBER",
9460  .read = queue_function_mem_read,
9461  .write = queue_function_mem_write,
9462 };
9463 
9464 static struct ast_custom_function queuemembercount_dep = {
9465  .name = "QUEUE_MEMBER_COUNT",
9466  .read = queue_function_qac_dep,
9467 };
9468 
9469 static struct ast_custom_function queuegetchannel_function = {
9470  .name = "QUEUE_GET_CHANNEL",
9472 };
9473 
9474 static struct ast_custom_function queuewaitingcount_function = {
9475  .name = "QUEUE_WAITING_COUNT",
9477 };
9478 
9479 static struct ast_custom_function queuememberlist_function = {
9480  .name = "QUEUE_MEMBER_LIST",
9482 };
9483 
9484 static struct ast_custom_function queuememberpenalty_function = {
9485  .name = "QUEUE_MEMBER_PENALTY",
9488 };
9489 
9490 /*! Reset the global queue rules parameters even if there is no "general" section of queuerules.conf */
9492 {
9493  realtime_rules = 0;
9494 }
9495 
9496 /*! Set the global queue rules parameters as defined in the "general" section of queuerules.conf */
9498 {
9499  const char *general_val = NULL;
9500  if ((general_val = ast_variable_retrieve(cfg, "general", "realtime_rules"))) {
9501  realtime_rules = ast_true(general_val);
9502  }
9503 }
9504 
9505 /*! \brief Reload the rules defined in queuerules.conf
9506  *
9507  * \param reload If 1, then only process queuerules.conf if the file
9508  * has changed since the last time we inspected it.
9509  * \return Always returns AST_MODULE_LOAD_SUCCESS
9510  */
9511 static int reload_queue_rules(int reload)
9512 {
9513  struct ast_config *cfg;
9514  struct rule_list *rl_iter, *new_rl;
9515  struct penalty_rule *pr_iter;
9516  char *rulecat = NULL;
9517  struct ast_variable *rulevar = NULL;
9518  struct ast_flags config_flags = { (reload && !realtime_rules) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
9519 
9520  if (!(cfg = ast_config_load("queuerules.conf", config_flags))) {
9521  ast_log(LOG_NOTICE, "No queuerules.conf file found, queues will not follow penalty rules\n");
9522  return AST_MODULE_LOAD_SUCCESS;
9523  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
9524  ast_log(LOG_NOTICE, "queuerules.conf has not changed since it was last loaded. Not taking any action.\n");
9525  return AST_MODULE_LOAD_SUCCESS;
9526  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
9527  ast_log(LOG_ERROR, "Config file queuerules.conf is in an invalid format. Aborting.\n");
9528  return AST_MODULE_LOAD_SUCCESS;
9529  }
9530 
9532  while ((rl_iter = AST_LIST_REMOVE_HEAD(&rule_lists, list))) {
9533  while ((pr_iter = AST_LIST_REMOVE_HEAD(&rl_iter->rules, list)))
9534  ast_free(pr_iter);
9535  ast_free(rl_iter);
9536  }
9538  while ((rulecat = ast_category_browse(cfg, rulecat))) {
9539  if (!strcasecmp(rulecat, "general")) {
9541  continue;
9542  }
9543  if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
9545  ast_config_destroy(cfg);
9546  return AST_MODULE_LOAD_DECLINE;
9547  } else {
9548  ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
9549  AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
9550  for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next)
9551  if(!strcasecmp(rulevar->name, "penaltychange"))
9552  insert_penaltychange(new_rl->name, rulevar->value, rulevar->lineno);
9553  else
9554  ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno);
9555  }
9556  }
9557 
9558  ast_config_destroy(cfg);
9559 
9560  if (realtime_rules && load_realtime_rules()) {
9562  return AST_MODULE_LOAD_DECLINE;
9563  }
9564 
9566  return AST_MODULE_LOAD_SUCCESS;
9567 }
9568 
9569 /*! Always set the global queue defaults, even if there is no "general" section in queues.conf */
9570 static void queue_reset_global_params(void)
9571 {
9572  queue_persistent_members = 0;
9573  autofill_default = 0;
9574  montype_default = 0;
9575  shared_lastcall = 0;
9576  negative_penalty_invalid = 0;
9577  log_membername_as_agent = 0;
9578  force_longest_waiting_caller = 0;
9579 }
9580 
9581 /*! Set the global queue parameters as defined in the "general" section of queues.conf */
9582 static void queue_set_global_params(struct ast_config *cfg)
9583 {
9584  const char *general_val = NULL;
9585  if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) {
9586  queue_persistent_members = ast_true(general_val);
9587  }
9588  if ((general_val = ast_variable_retrieve(cfg, "general", "autofill"))) {
9589  autofill_default = ast_true(general_val);
9590  }
9591  if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) {
9592  if (!strcasecmp(general_val, "mixmonitor"))
9593  montype_default = 1;
9594  }
9595  if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall"))) {
9596  shared_lastcall = ast_true(general_val);
9597  }
9598  if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid"))) {
9599  negative_penalty_invalid = ast_true(general_val);
9600  }
9601  if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent"))) {
9602  log_membername_as_agent = ast_true(general_val);
9603  }
9604  if ((general_val = ast_variable_retrieve(cfg, "general", "force_longest_waiting_caller"))) {
9605  force_longest_waiting_caller = ast_true(general_val);
9606  }
9607 }
9608 
9609 /*! \brief reload information pertaining to a single member
9610  *
9611  * This function is called when a member = line is encountered in
9612  * queues.conf.
9613  *
9614  * \param memberdata The part after member = in the config file
9615  * \param q The queue to which this member belongs
9616  */
9617 static void reload_single_member(const char *memberdata, struct call_queue *q)
9618 {
9619  char *membername, *interface, *state_interface, *tmp;
9620  char *parse;
9621  struct member *cur, *newm;
9622  struct member tmpmem;
9623  int penalty;
9624  int ringinuse;
9625  int wrapuptime;
9626  AST_DECLARE_APP_ARGS(args,
9627  AST_APP_ARG(interface);
9628  AST_APP_ARG(penalty);
9629  AST_APP_ARG(membername);
9630  AST_APP_ARG(state_interface);
9631  AST_APP_ARG(ringinuse);
9632  AST_APP_ARG(wrapuptime);
9633  );
9634 
9635  if (ast_strlen_zero(memberdata)) {
9636  ast_log(LOG_WARNING, "Empty queue member definition. Moving on!\n");
9637  return;
9638  }
9639 
9640  /* Add a new member */
9641  parse = ast_strdupa(memberdata);
9642 
9643  AST_STANDARD_APP_ARGS(args, parse);
9644 
9645  interface = args.interface;
9646  if (!ast_strlen_zero(args.penalty)) {
9647  tmp = args.penalty;
9648  ast_strip(tmp);
9649  penalty = atoi(tmp);
9650  if (penalty < 0) {
9651  penalty = 0;
9652  }
9653  } else {
9654  penalty = 0;
9655  }
9656 
9657  if (!ast_strlen_zero(args.membername)) {
9658  membername = args.membername;
9659  ast_strip(membername);
9660  } else {
9661  membername = interface;
9662  }
9663 
9664  if (!ast_strlen_zero(args.state_interface)) {
9665  state_interface = args.state_interface;
9666  ast_strip(state_interface);
9667  } else {
9668  state_interface = interface;
9669  }
9670 
9671  if (!ast_strlen_zero(args.ringinuse)) {
9672  tmp = args.ringinuse;
9673  ast_strip(tmp);
9674  if (ast_true(tmp)) {
9675  ringinuse = 1;
9676  } else if (ast_false(tmp)) {
9677  ringinuse = 0;
9678  } else {
9679  ast_log(LOG_ERROR, "Member %s has an invalid ringinuse value. Using %s ringinuse value.\n",
9680  membername, q->name);
9681  ringinuse = q->ringinuse;
9682  }
9683  } else {
9684  ringinuse = q->ringinuse;
9685  }
9686 
9687  if (!ast_strlen_zero(args.wrapuptime)) {
9688  tmp = args.wrapuptime;
9689  ast_strip(tmp);
9690  wrapuptime = atoi(tmp);
9691  if (wrapuptime < 0) {
9692  wrapuptime = 0;
9693  }
9694  } else {
9695  wrapuptime = 0;
9696  }
9697 
9698  /* Find the old position in the list */
9699  ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
9700  cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);
9701 
9702  if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse, wrapuptime))) {
9703  newm->wrapuptime = wrapuptime;
9704  if (cur) {
9705  ao2_lock(q->members);
9706  /* Round Robin Queue Position must be copied if this is replacing an existing member */
9707  newm->queuepos = cur->queuepos;
9708  /* Don't reset agent stats either */
9709  newm->calls = cur->calls;
9710  newm->lastcall = cur->lastcall;
9711 
9712  ao2_link(q->members, newm);
9713  ao2_unlink(q->members, cur);
9714  ao2_unlock(q->members);
9715  } else {
9716  /* Otherwise we need to add using the function that will apply a round robin queue position manually. */
9717  member_add_to_queue(q, newm);
9718  }
9719  ao2_ref(newm, -1);
9720  }
9721  newm = NULL;
9722 
9723  if (cur) {
9724  ao2_ref(cur, -1);
9725  }
9726 }
9727 
9728 static int mark_member_dead(void *obj, void *arg, int flags)
9729 {
9730  struct member *member = obj;
9731  if (!member->dynamic && !member->realtime) {
9732  member->delme = 1;
9733  }
9734  return 0;
9735 }
9736 
9737 static int kill_dead_members(void *obj, void *arg, int flags)
9738 {
9739  struct member *member = obj;
9740 
9741  if (!member->delme) {
9742  member->status = get_queue_member_status(member);
9743  return 0;
9744  } else {
9745  return CMP_MATCH;
9746  }
9747 }
9748 
9749 /*! \brief Reload information pertaining to a particular queue
9750  *
9751  * Once we have isolated a queue within reload_queues, we call this. This will either
9752  * reload information for the queue or if we're just reloading member information, we'll just
9753  * reload that without touching other settings within the queue
9754  *
9755  * \param cfg The configuration which we are reading
9756  * \param mask Tells us what information we need to reload
9757  * \param queuename The name of the queue we are reloading information from
9758  */
9759 static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
9760 {
9761  int new;
9762  struct call_queue *q = NULL;
9763  struct member *member;
9764  /*We're defining a queue*/
9765  struct call_queue tmpq = {
9766  .name = queuename,
9767  };
9768  const char *tmpvar;
9769  const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
9770  const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
9771  int prev_weight = 0;
9772  struct ast_variable *var;
9773  struct ao2_iterator mem_iter;
9774 
9775  if (!(q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find queue for reload"))) {
9776  if (queue_reload) {
9777  /* Make one then */
9778  if (!(q = alloc_queue(queuename))) {
9779  return;
9780  }
9781  } else {
9782  /* Since we're not reloading queues, this means that we found a queue
9783  * in the configuration file which we don't know about yet. Just return.
9784  */
9785  return;
9786  }
9787  new = 1;
9788  } else {
9789  new = 0;
9790  }
9791 
9792  if (!new) {
9793  ao2_lock(q);
9794  prev_weight = q->weight ? 1 : 0;
9795  }
9796  /* Check if we already found a queue with this name in the config file */
9797  if (q->found) {
9798  ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", queuename);
9799  if (!new) {
9800  /* It should be impossible to *not* hit this case*/
9801  ao2_unlock(q);
9802  }
9803  queue_t_unref(q, "We exist! Expiring temporary pointer");
9804  return;
9805  }
9806  /* Due to the fact that the "linear" strategy will have a different allocation
9807  * scheme for queue members, we must devise the queue's strategy before other initializations.
9808  * To be specific, the linear strategy needs to function like a linked list, meaning the ao2
9809  * container used will have only a single bucket instead of the typical number.
9810  */
9811  if (queue_reload) {
9812  if ((tmpvar = ast_variable_retrieve(cfg, queuename, "strategy"))) {
9813  q->strategy = strat2int(tmpvar);
9814  if (q->strategy < 0) {
9815  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
9816  tmpvar, q->name);
9817  q->strategy = QUEUE_STRATEGY_RINGALL;
9818  }
9819  } else {
9820  q->strategy = QUEUE_STRATEGY_RINGALL;
9821  }
9822  init_queue(q);
9823  }
9824  if (member_reload) {
9825  ao2_callback(q->members, OBJ_NODATA, mark_member_dead, NULL);
9826  q->found = 1;
9827  }
9828 
9829  /* On the first pass we just read the parameters of the queue */
9830  for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
9831  if (queue_reload && strcasecmp(var->name, "member")) {
9832  queue_set_param(q, var->name, var->value, var->lineno, 1);
9833  }
9834  }
9835 
9836  /* On the second pass, we read members */
9837  for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
9838  if (member_reload && !strcasecmp(var->name, "member")) {
9839  reload_single_member(var->value, q);
9840  }
9841  }
9842 
9843  /* Update ringinuse for dynamic members */
9844  if (member_reload) {
9845  ao2_lock(q->members);
9847  while ((member = ao2_iterator_next(&mem_iter))) {
9848  if (member->dynamic) {
9849  member->ringinuse = q->ringinuse;
9850  }
9851  ao2_ref(member, -1);
9852  }
9853  ao2_iterator_destroy(&mem_iter);
9854  ao2_unlock(q->members);
9855  }
9856 
9857  /* At this point, we've determined if the queue has a weight, so update use_weight
9858  * as appropriate
9859  */
9860  if (!q->weight && prev_weight) {
9861  ast_atomic_fetchadd_int(&use_weight, -1);
9862  } else if (q->weight && !prev_weight) {
9863  ast_atomic_fetchadd_int(&use_weight, +1);
9864  }
9865 
9866  /* Free remaining members marked as delme */
9867  if (member_reload) {
9868  ao2_lock(q->members);
9869  ao2_callback(q->members, OBJ_NODATA | OBJ_MULTIPLE, queue_delme_members_decrement_followers, q);
9870  ao2_callback(q->members, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_members, q);
9871  ao2_unlock(q->members);
9872  }
9873 
9874  if (new) {
9875  queues_t_link(queues, q, "Add queue to container");
9876  } else {
9877  ao2_unlock(q);
9878  }
9879  queue_t_unref(q, "Expiring creation reference");
9880 }
9881 
9882 static int mark_unfound(void *obj, void *arg, int flags)
9883 {
9884  struct call_queue *q = obj;
9885  char *queuename = arg;
9886  if (!q->realtime && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
9887  q->found = 0;
9888  }
9889  return 0;
9890 }
9891 
9892 static int kill_if_unfound(void *obj, void *arg, int flags)
9893 {
9894  struct call_queue *q = obj;
9895  char *queuename = arg;
9896  if (!q->realtime && !q->found && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
9897  q->dead = 1;
9898  return CMP_MATCH;
9899  } else {
9900  return 0;
9901  }
9902 }
9903 
9904 /*! \brief reload the queues.conf file
9905  *
9906  * This function reloads the information in the general section of the queues.conf
9907  * file and potentially more, depending on the value of mask.
9908  *
9909  * \param reload 0 if we are calling this the first time, 1 every other time
9910  * \param mask Gives flags telling us what information to actually reload
9911  * \param queuename If set to a non-zero string, then only reload information from
9912  * that particular queue. Otherwise inspect all queues
9913  * \retval -1 Failure occurred
9914  * \retval 0 All clear!
9915  */
9916 static int reload_queues(int reload, struct ast_flags *mask, const char *queuename)
9917 {
9918  struct ast_config *cfg;
9919  char *cat;
9920  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
9921  const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
9922 
9923  if (!(cfg = ast_config_load("queues.conf", config_flags))) {
9924  ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
9925  return -1;
9926  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
9927  return 0;
9928  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
9929  ast_log(LOG_ERROR, "Config file queues.conf is in an invalid format. Aborting.\n");
9930  return -1;
9931  }
9932 
9933  /* We've made it here, so it looks like we're doing operations on all queues. */
9934  ao2_lock(queues);
9935 
9936  /* Mark non-realtime queues not found at the beginning. */
9937  ao2_callback(queues, OBJ_NODATA, mark_unfound, (char *) queuename);
9938 
9939  /* Chug through config file. */
9940  cat = NULL;
9942  while ((cat = ast_category_browse(cfg, cat)) ) {
9943  if (!strcasecmp(cat, "general") && queue_reload) {
9945  continue;
9946  }
9947  if (ast_strlen_zero(queuename) || !strcasecmp(cat, queuename))
9948  reload_single_queue(cfg, mask, cat);
9949  }
9950 
9951  ast_config_destroy(cfg);
9952  if (queue_reload) {
9953  /* Unlink and mark dead all non-realtime queues that were not found in the configuration file. */
9954  ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NOLOCK, kill_if_unfound, (char *) queuename);
9955  }
9956  ao2_unlock(queues);
9957  return 0;
9958 }
9959 
9960 /*! \brief Facilitates resetting statistics for a queue
9961  *
9962  * This function actually does not reset any statistics, but
9963  * rather finds a call_queue struct which corresponds to the
9964  * passed-in queue name and passes that structure to the
9965  * clear_queue function. If no queuename is passed in, then
9966  * all queues will have their statistics reset.
9967  *
9968  * \param queuename The name of the queue to reset the statistics
9969  * for. If this is NULL or zero-length, then this means to reset
9970  * the statistics for all queues
9971  * \retval 0 always
9972  */
9973 static int clear_stats(const char *queuename)
9974 {
9975  struct call_queue *q;
9976  struct ao2_iterator queue_iter;
9977 
9978  queue_iter = ao2_iterator_init(queues, 0);
9979  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9980  ao2_lock(q);
9981  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
9982  clear_queue(q);
9983  ao2_unlock(q);
9984  queue_t_unref(q, "Done with iterator");
9985  }
9986  ao2_iterator_destroy(&queue_iter);
9987  return 0;
9988 }
9989 
9990 /*! \brief The command center for all reload operations
9991  *
9992  * Whenever any piece of queue information is to be reloaded, this function
9993  * is called. It interprets the flags set in the mask parameter and acts
9994  * based on how they are set.
9995  *
9996  * \param reload True if we are reloading information, false if we are loading
9997  * information for the first time.
9998  * \param mask A bitmask which tells the handler what actions to take
9999  * \param queuename The name of the queue on which we wish to take action
10000  * \retval 0 All reloads were successful
10001  * \retval non-zero There was a failure
10002  */
10003 static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
10004 {
10005  int res = 0;
10006 
10007  if (ast_test_flag(mask, QUEUE_RELOAD_RULES)) {
10008  res |= reload_queue_rules(reload);
10009  }
10010  if (ast_test_flag(mask, QUEUE_RESET_STATS)) {
10011  res |= clear_stats(queuename);
10012  }
10013  if (ast_test_flag(mask, (QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER))) {
10014  res |= reload_queues(reload, mask, queuename);
10015  }
10016  return res;
10017 }
10018 
10019 /*! \brief direct output to manager or cli with proper terminator */
10020 static void do_print(struct mansession *s, int fd, const char *str)
10021 {
10022  if (s) {
10023  astman_append(s, "%s\r\n", str);
10024  } else {
10025  ast_cli(fd, "%s\n", str);
10026  }
10027 }
10028 
10029 /*! \brief Print a single queue to AMI or the CLI */
10030 static void print_queue(struct mansession *s, int fd, struct call_queue *q)
10031 {
10032  float sl;
10033  float sl2;
10034  struct ao2_iterator mem_iter;
10035  struct ast_str *out = ast_str_alloca(512);
10036  time_t now = time(NULL);
10037 
10038  ast_str_set(&out, 0, "%s has %d calls (max ", q->name, q->count);
10039  if (q->maxlen) {
10040  ast_str_append(&out, 0, "%d", q->maxlen);
10041  } else {
10042  ast_str_append(&out, 0, "unlimited");
10043  }
10044  sl = 0;
10045  sl2 = 0;
10046  if (q->callscompleted > 0) {
10047  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
10048  }
10049  if (q->callscompleted + q->callsabandoned > 0) {
10050  sl2 =100 * (((float)q->callsabandonedinsl + (float)q->callscompletedinsl) / ((float)q->callsabandoned + (float)q->callscompleted));
10051  }
10052 
10053  ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime), W:%d, C:%d, A:%d, SL:%2.1f%%, SL2:%2.1f%% within %ds",
10054  int2strat(q->strategy), q->holdtime, q->talktime, q->weight, q->callscompleted, q->callsabandoned, sl, sl2, q->servicelevel);
10055  do_print(s, fd, ast_str_buffer(out));
10056  if (!ao2_container_count(q->members)) {
10057  do_print(s, fd, " No Members");
10058  } else {
10059  struct member *mem;
10060 
10061  do_print(s, fd, " Members: ");
10062  mem_iter = ao2_iterator_init(q->members, 0);
10063  while ((mem = ao2_iterator_next(&mem_iter))) {
10064  ast_str_set(&out, 0, " %s", mem->membername);
10065  if (strcasecmp(mem->membername, mem->interface)) {
10066  ast_str_append(&out, 0, " (%s", mem->interface);
10067  if (!ast_strlen_zero(mem->state_interface)
10068  && strcmp(mem->state_interface, mem->interface)) {
10069  ast_str_append(&out, 0, " from %s", mem->state_interface);
10070  }
10071  ast_str_append(&out, 0, ")");
10072  }
10073  if (mem->penalty) {
10074  ast_str_append(&out, 0, " with penalty %d", mem->penalty);
10075  }
10076 
10077  ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
10078 
10079  ast_str_append(&out, 0, "%s%s%s%s%s%s%s%s%s",
10080  mem->dynamic ? ast_term_color(COLOR_CYAN, COLOR_BLACK) : "", mem->dynamic ? " (dynamic)" : "", ast_term_reset(),
10081  mem->realtime ? ast_term_color(COLOR_MAGENTA, COLOR_BLACK) : "", mem->realtime ? " (realtime)" : "", ast_term_reset(),
10082  mem->starttime ? ast_term_color(COLOR_BROWN, COLOR_BLACK) : "", mem->starttime ? " (in call)" : "", ast_term_reset());
10083 
10084  if (mem->paused) {
10085  ast_str_append(&out, 0, " %s(paused%s%s was %ld secs ago)%s",
10086  ast_term_color(COLOR_BROWN, COLOR_BLACK),
10087  ast_strlen_zero(mem->reason_paused) ? "" : ":",
10088  ast_strlen_zero(mem->reason_paused) ? "" : mem->reason_paused,
10089  (long) (now - mem->lastpause),
10090  ast_term_reset());
10091  }
10092 
10093  ast_str_append(&out, 0, " (%s%s%s)",
10096  COLOR_RED : COLOR_GREEN, COLOR_BLACK),
10098  if (mem->calls) {
10099  ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
10100  mem->calls, (long) (now - mem->lastcall));
10101  } else {
10102  ast_str_append(&out, 0, " has taken no calls yet");
10103  }
10104  ast_str_append(&out, 0, " %s(login was %ld secs ago)%s",
10105  ast_term_color(COLOR_BROWN, COLOR_BLACK),
10106  (long) (now - mem->logintime),
10107  ast_term_reset());
10108  do_print(s, fd, ast_str_buffer(out));
10109  ao2_ref(mem, -1);
10110  }
10111  ao2_iterator_destroy(&mem_iter);
10112  }
10113  if (!q->head) {
10114  do_print(s, fd, " No Callers");
10115  } else {
10116  struct queue_ent *qe;
10117  int pos = 1;
10118 
10119  do_print(s, fd, " Callers: ");
10120  for (qe = q->head; qe; qe = qe->next) {
10121  ast_str_set(&out, 0, " %d. %s (wait: %ld:%2.2ld, prio: %d)",
10122  pos++, ast_channel_name(qe->chan), (long) (now - qe->start) / 60,
10123  (long) (now - qe->start) % 60, qe->prio);
10124  do_print(s, fd, ast_str_buffer(out));
10125  }
10126  }
10127  do_print(s, fd, ""); /* blank line between entries */
10128 }
10129 
10131 
10132 /*!
10133  * \brief Show queue(s) status and statistics
10134  *
10135  * List the queues strategy, calls processed, members logged in,
10136  * other queue statistics such as avg hold time.
10137 */
10138 static char *__queues_show(struct mansession *s, int fd, int argc, const char * const *argv)
10139 {
10140  struct call_queue *q;
10141  struct ast_str *out = ast_str_alloca(512);
10142  struct ao2_container *sorted_queues;
10143 
10144  struct ao2_iterator queue_iter;
10145  int found = 0;
10146 
10147  if (argc != 2 && argc != 3) {
10148  return CLI_SHOWUSAGE;
10149  }
10150 
10151  if (argc == 3) { /* specific queue */
10152  if ((q = find_load_queue_rt_friendly(argv[2]))) {
10153  ao2_lock(q);
10154  print_queue(s, fd, q);
10155  ao2_unlock(q);
10156  queue_unref(q);
10157  } else {
10158  ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
10159  do_print(s, fd, ast_str_buffer(out));
10160  }
10161  return CLI_SUCCESS;
10162  }
10163 
10164  if (ast_check_realtime("queues")) {
10165  /* This block is to find any queues which are defined in realtime but
10166  * which have not yet been added to the in-core container
10167  */
10168  struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
10169  if (cfg) {
10170  char *category = NULL;
10171  while ((category = ast_category_browse(cfg, category))) {
10172  const char *queuename = ast_variable_retrieve(cfg, category, "name");
10173  if (ast_strlen_zero(queuename)) {
10174  ast_log(LOG_WARNING, "Ignoring realtime queue with a NULL or empty 'name.'\n");
10175  continue;
10176  }
10177  if ((q = find_load_queue_rt_friendly(queuename))) {
10178  queue_t_unref(q, "Done with temporary pointer");
10179  }
10180  }
10181  ast_config_destroy(cfg);
10182  }
10183  }
10184 
10185  /*
10186  * Snapping a copy of the container prevents having to lock both the queues container
10187  * and the queue itself at the same time. It also allows us to sort the entries.
10188  */
10189  sorted_queues = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, call_queue_sort_fn, NULL);
10190  if (!sorted_queues) {
10191  return CLI_SUCCESS;
10192  }
10193  if (ao2_container_dup(sorted_queues, queues, 0)) {
10194  ao2_ref(sorted_queues, -1);
10195  return CLI_SUCCESS;
10196  }
10197 
10198  /*
10199  * No need to lock the container since it's temporary and static.
10200  * We also unlink the entries as we use them so the container is
10201  * empty when the iterator finishes. We can then just unref the container.
10202  */
10203  queue_iter = ao2_iterator_init(sorted_queues, AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK);
10204  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10205  struct call_queue *realtime_queue = NULL;
10206  ao2_lock(q);
10207  /* This check is to make sure we don't print information for realtime
10208  * queues which have been deleted from realtime but which have not yet
10209  * been deleted from the in-core container. Only do this if we're not
10210  * looking for a specific queue.
10211  */
10212  if (q->realtime) {
10213  realtime_queue = find_load_queue_rt_friendly(q->name);
10214  if (!realtime_queue) {
10215  ao2_unlock(q);
10216  queue_t_unref(q, "Done with iterator");
10217  continue;
10218  }
10219  queue_t_unref(realtime_queue, "Queue is already in memory");
10220  }
10221 
10222  found = 1;
10223  print_queue(s, fd, q);
10224 
10225  ao2_unlock(q);
10226  queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
10227  }
10228  ao2_iterator_destroy(&queue_iter);
10229  ao2_ref(sorted_queues, -1);
10230  if (!found) {
10231  ast_str_set(&out, 0, "No queues.");
10232  do_print(s, fd, ast_str_buffer(out));
10233  }
10234  return CLI_SUCCESS;
10235 }
10236 
10237 /*!
10238  * \brief Check if a given word is in a space-delimited list
10239  *
10240  * \param list Space delimited list of words
10241  * \param word The word used to search the list
10242  *
10243  * \note This function will not return 1 if the word is at the very end of the
10244  * list (followed immediately by a \0, not a space) since it is used for
10245  * checking tab-completion and a word at the end is still being tab-completed.
10246  *
10247  * \retval 1 if the word is found
10248  * \retval 0 if the word is not found
10249 */
10250 static int word_in_list(const char *list, const char *word) {
10251  int list_len, word_len = strlen(word);
10252  const char *find, *end_find, *end_list;
10253 
10254  /* strip whitespace from front */
10255  while(isspace(*list)) {
10256  list++;
10257  }
10258 
10259  while((find = strstr(list, word))) {
10260  /* beginning of find starts inside another word? */
10261  if (find != list && *(find - 1) != ' ') {
10262  list = find;
10263  /* strip word from front */
10264  while(!isspace(*list) && *list != '\0') {
10265  list++;
10266  }
10267  /* strip whitespace from front */
10268  while(isspace(*list)) {
10269  list++;
10270  }
10271  continue;
10272  }
10273 
10274  /* end of find ends inside another word or at very end of list? */
10275  list_len = strlen(list);
10276  end_find = find + word_len;
10277  end_list = list + list_len;
10278  if (end_find == end_list || *end_find != ' ') {
10279  list = find;
10280  /* strip word from front */
10281  while(!isspace(*list) && *list != '\0') {
10282  list++;
10283  }
10284  /* strip whitespace from front */
10285  while(isspace(*list)) {
10286  list++;
10287  }
10288  continue;
10289  }
10290 
10291  /* terminating conditions satisfied, word at beginning or separated by ' ' */
10292  return 1;
10293  }
10294 
10295  return 0;
10296 }
10297 
10298 /*!
10299  * \brief Check if a given word is in a space-delimited list
10300  *
10301  * \param line The line as typed not including the current word being completed
10302  * \param word The word currently being completed
10303  * \param pos The number of completed words in line
10304  * \param state The nth desired completion option
10305  * \param word_list_offset Offset into the line where the list of queues begins. If non-zero, queues in the list will not be offered for further completion.
10306  *
10307  * \return Returns the queue tab-completion for the given word and state
10308 */
10309 static char *complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
10310 {
10311  struct call_queue *q;
10312  char *ret = NULL;
10313  int which = 0;
10314  int wordlen = strlen(word);
10315  struct ao2_iterator queue_iter;
10316  const char *word_list = NULL;
10317 
10318  /* for certain commands, already completed items should be left out of
10319  * the list */
10320  if (word_list_offset && strlen(line) >= word_list_offset) {
10321  word_list = line + word_list_offset;
10322  }
10323 
10324  queue_iter = ao2_iterator_init(queues, 0);
10325  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10326  if (!strncasecmp(word, q->name, wordlen) && ++which > state
10327  && (!word_list_offset || !word_in_list(word_list, q->name))) {
10328  ret = ast_strdup(q->name);
10329  queue_t_unref(q, "Done with iterator");
10330  break;
10331  }
10332  queue_t_unref(q, "Done with iterator");
10333  }
10334  ao2_iterator_destroy(&queue_iter);
10335 
10336  /* Pretend "rules" is at the end of the queues list in certain
10337  * circumstances since it is an alternate command that should be
10338  * tab-completable for "queue show" */
10339  if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
10340  ret = ast_strdup("rules");
10341  }
10342 
10343  return ret;
10344 }
10345 
10346 static char *complete_queue_show(const char *line, const char *word, int pos, int state)
10347 {
10348  if (pos == 2) {
10349  return complete_queue(line, word, pos, state, 0);
10350  }
10351  return NULL;
10352 }
10353 
10354 static char *queue_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
10355 {
10356  switch ( cmd ) {
10357  case CLI_INIT:
10358  e->command = "queue show";
10359  e->usage =
10360  "Usage: queue show\n"
10361  " Provides summary information on a specified queue.\n";
10362  return NULL;
10363  case CLI_GENERATE:
10364  return complete_queue_show(a->line, a->word, a->pos, a->n);
10365  }
10366 
10367  return __queues_show(NULL, a->fd, a->argc, a->argv);
10368 }
10369 
10370 static int manager_queue_rule_show(struct mansession *s, const struct message *m)
10371 {
10372  const char *rule = astman_get_header(m, "Rule");
10373  const char *id = astman_get_header(m, "ActionID");
10374  struct rule_list *rl_iter;
10375  struct penalty_rule *pr_iter;
10376 
10377  astman_append(s, "Response: Success\r\n");
10378  if (!ast_strlen_zero(id)) {
10379  astman_append(s, "ActionID: %s\r\n", id);
10380  }
10381 
10383  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
10384  if (ast_strlen_zero(rule) || !strcasecmp(rule, rl_iter->name)) {
10385  astman_append(s, "RuleList: %s\r\n", rl_iter->name);
10386  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
10387  astman_append(s, "Rule: %d,%s%d,%s%d\r\n", pr_iter->time, pr_iter->max_relative && pr_iter->max_value >= 0 ? "+" : "", pr_iter->max_value, pr_iter->min_relative && pr_iter->min_value >= 0 ? "+" : "", pr_iter->min_value );
10388  }
10389  if (!ast_strlen_zero(rule)) {
10390  break;
10391  }
10392  }
10393  }
10395 
10396  /*
10397  * Two blank lines instead of one because the Response and
10398  * ActionID headers used to not be present.
10399  */
10400  astman_append(s, "\r\n\r\n");
10401 
10402  return RESULT_SUCCESS;
10403 }
10404 
10405 /*! \brief Summary of queue info via the AMI */
10406 static int manager_queues_summary(struct mansession *s, const struct message *m)
10407 {
10408  time_t now;
10409  int qmemcount = 0;
10410  int qmemavail = 0;
10411  int qchancount = 0;
10412  int qlongestholdtime = 0;
10413  int qsummaries = 0;
10414  const char *id = astman_get_header(m, "ActionID");
10415  const char *queuefilter = astman_get_header(m, "Queue");
10416  char idText[256];
10417  struct call_queue *q;
10418  struct queue_ent *qe;
10419  struct member *mem;
10420  struct ao2_iterator queue_iter;
10421  struct ao2_iterator mem_iter;
10422 
10423  if (ast_check_realtime("queues")) {
10424  load_realtime_queues(queuefilter);
10425  }
10426 
10427  astman_send_listack(s, m, "Queue summary will follow", "start");
10428  time(&now);
10429  idText[0] = '\0';
10430  if (!ast_strlen_zero(id)) {
10431  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
10432  }
10433  queue_iter = ao2_iterator_init(queues, 0);
10434  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10435  ao2_lock(q);
10436 
10437  /* List queue properties */
10438  if (ast_strlen_zero(queuefilter) || !strcasecmp(q->name, queuefilter)) {
10439  /* Reset the necessary local variables if no queuefilter is set*/
10440  qmemcount = 0;
10441  qmemavail = 0;
10442  qchancount = 0;
10443  qlongestholdtime = 0;
10444 
10445  /* List Queue Members */
10446  mem_iter = ao2_iterator_init(q->members, 0);
10447  while ((mem = ao2_iterator_next(&mem_iter))) {
10448  if ((mem->status != AST_DEVICE_UNAVAILABLE) && (mem->status != AST_DEVICE_INVALID)) {
10449  ++qmemcount;
10450  if (member_status_available(mem->status) && !mem->paused) {
10451  ++qmemavail;
10452  }
10453  }
10454  ao2_ref(mem, -1);
10455  }
10456  ao2_iterator_destroy(&mem_iter);
10457  for (qe = q->head; qe; qe = qe->next) {
10458  if ((now - qe->start) > qlongestholdtime) {
10459  qlongestholdtime = now - qe->start;
10460  }
10461  ++qchancount;
10462  }
10463  astman_append(s, "Event: QueueSummary\r\n"
10464  "Queue: %s\r\n"
10465  "LoggedIn: %d\r\n"
10466  "Available: %d\r\n"
10467  "Callers: %d\r\n"
10468  "HoldTime: %d\r\n"
10469  "TalkTime: %d\r\n"
10470  "LongestHoldTime: %d\r\n"
10471  "%s"
10472  "\r\n",
10473  q->name, qmemcount, qmemavail, qchancount, q->holdtime, q->talktime, qlongestholdtime, idText);
10474  ++qsummaries;
10475  }
10476  ao2_unlock(q);
10477  queue_t_unref(q, "Done with iterator");
10478  }
10479  ao2_iterator_destroy(&queue_iter);
10480 
10481  astman_send_list_complete_start(s, m, "QueueSummaryComplete", qsummaries);
10483 
10484  return RESULT_SUCCESS;
10485 }
10486 
10487 /*! \brief Queue status info via AMI */
10488 static int manager_queues_status(struct mansession *s, const struct message *m)
10489 {
10490  time_t now;
10491  int pos;
10492  int q_items = 0;
10493  const char *id = astman_get_header(m,"ActionID");
10494  const char *queuefilter = astman_get_header(m,"Queue");
10495  const char *memberfilter = astman_get_header(m,"Member");
10496  char idText[256];
10497  struct call_queue *q;
10498  struct queue_ent *qe;
10499  float sl = 0;
10500  float sl2 = 0;
10501  struct member *mem;
10502  struct ao2_iterator queue_iter;
10503  struct ao2_iterator mem_iter;
10504 
10505  if (ast_check_realtime("queues")) {
10506  load_realtime_queues(queuefilter);
10507  }
10508 
10509  astman_send_listack(s, m, "Queue status will follow", "start");
10510  time(&now);
10511  idText[0] = '\0';
10512  if (!ast_strlen_zero(id)) {
10513  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
10514  }
10515 
10516  queue_iter = ao2_iterator_init(queues, 0);
10517  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10518  ao2_lock(q);
10519 
10520  /* List queue properties */
10521  if (ast_strlen_zero(queuefilter) || !strcasecmp(q->name, queuefilter)) {
10522  sl = ((q->callscompleted > 0) ? 100 * ((float)q->callscompletedinsl / (float)q->callscompleted) : 0);
10523  sl2 = (((q->callscompleted + q->callsabandoned) > 0) ? 100 * (((float)q->callsabandonedinsl + (float)q->callscompletedinsl) / ((float)q->callsabandoned + (float)q->callscompleted)) : 0);
10524 
10525  astman_append(s, "Event: QueueParams\r\n"
10526  "Queue: %s\r\n"
10527  "Max: %d\r\n"
10528  "Strategy: %s\r\n"
10529  "Calls: %d\r\n"
10530  "Holdtime: %d\r\n"
10531  "TalkTime: %d\r\n"
10532  "Completed: %d\r\n"
10533  "Abandoned: %d\r\n"
10534  "ServiceLevel: %d\r\n"
10535  "ServicelevelPerf: %2.1f\r\n"
10536  "ServicelevelPerf2: %2.1f\r\n"
10537  "Weight: %d\r\n"
10538  "%s"
10539  "\r\n",
10540  q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted,
10541  q->callsabandoned, q->servicelevel, sl, sl2, q->weight, idText);
10542  ++q_items;
10543 
10544  /* List Queue Members */
10545  mem_iter = ao2_iterator_init(q->members, 0);
10546  while ((mem = ao2_iterator_next(&mem_iter))) {
10547  if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter) || !strcmp(mem->membername, memberfilter)) {
10548  astman_append(s, "Event: QueueMember\r\n"
10549  "Queue: %s\r\n"
10550  "Name: %s\r\n"
10551  "Location: %s\r\n"
10552  "StateInterface: %s\r\n"
10553  "Membership: %s\r\n"
10554  "Penalty: %d\r\n"
10555  "CallsTaken: %d\r\n"
10556  "LastCall: %d\r\n"
10557  "LastPause: %d\r\n"
10558  "LoginTime: %d\r\n"
10559  "InCall: %d\r\n"
10560  "Status: %d\r\n"
10561  "Paused: %d\r\n"
10562  "PausedReason: %s\r\n"
10563  "Wrapuptime: %d\r\n"
10564  "%s"
10565  "\r\n",
10566  q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
10567  mem->penalty, mem->calls, (int)mem->lastcall, (int)mem->lastpause, (int)mem->logintime, mem->starttime ? 1 : 0, mem->status,
10568  mem->paused, mem->reason_paused, mem->wrapuptime, idText);
10569  ++q_items;
10570  }
10571  ao2_ref(mem, -1);
10572  }
10573  ao2_iterator_destroy(&mem_iter);
10574 
10575  /* List Queue Entries */
10576  pos = 1;
10577  for (qe = q->head; qe; qe = qe->next) {
10578  astman_append(s, "Event: QueueEntry\r\n"
10579  "Queue: %s\r\n"
10580  "Position: %d\r\n"
10581  "Channel: %s\r\n"
10582  "Uniqueid: %s\r\n"
10583  "CallerIDNum: %s\r\n"
10584  "CallerIDName: %s\r\n"
10585  "ConnectedLineNum: %s\r\n"
10586  "ConnectedLineName: %s\r\n"
10587  "Wait: %ld\r\n"
10588  "Priority: %d\r\n"
10589  "%s"
10590  "\r\n",
10591  q->name, pos++, ast_channel_name(qe->chan), ast_channel_uniqueid(qe->chan),
10592  S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
10593  S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
10594  S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
10595  S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
10596  (long) (now - qe->start), qe->prio, idText);
10597  ++q_items;
10598  }
10599  }
10600  ao2_unlock(q);
10601  queue_t_unref(q, "Done with iterator");
10602  }
10603  ao2_iterator_destroy(&queue_iter);
10604 
10605  astman_send_list_complete_start(s, m, "QueueStatusComplete", q_items);
10607 
10608  return RESULT_SUCCESS;
10609 }
10610 
10611 static int manager_add_queue_member(struct mansession *s, const struct message *m)
10612 {
10613  const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface, *wrapuptime_s;
10614  int paused, penalty, wrapuptime = 0;
10615 
10616  queuename = astman_get_header(m, "Queue");
10617  interface = astman_get_header(m, "Interface");
10618  penalty_s = astman_get_header(m, "Penalty");
10619  paused_s = astman_get_header(m, "Paused");
10620  membername = astman_get_header(m, "MemberName");
10621  state_interface = astman_get_header(m, "StateInterface");
10622  wrapuptime_s = astman_get_header(m, "Wrapuptime");
10623 
10624  if (ast_strlen_zero(queuename)) {
10625  astman_send_error(s, m, "'Queue' not specified.");
10626  return 0;
10627  }
10628 
10629  if (ast_strlen_zero(interface)) {
10630  astman_send_error(s, m, "'Interface' not specified.");
10631  return 0;
10632  }
10633 
10634  if (ast_strlen_zero(penalty_s)) {
10635  penalty = 0;
10636  } else if (sscanf(penalty_s, "%30d", &penalty) != 1 || penalty < 0) {
10637  penalty = 0;
10638  }
10639 
10640  if (ast_strlen_zero(wrapuptime_s)) {
10641  wrapuptime = 0;
10642  } else if (sscanf(wrapuptime_s, "%30d", &wrapuptime) != 1 || wrapuptime < 0) {
10643  wrapuptime = 0;
10644  }
10645 
10646  if (ast_strlen_zero(paused_s)) {
10647  paused = 0;
10648  } else {
10649  paused = abs(ast_true(paused_s));
10650  }
10651 
10652  switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface, NULL, wrapuptime)) {
10653  case RES_OKAY:
10654  if (ast_strlen_zero(membername) || !log_membername_as_agent) {
10655  ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
10656  } else {
10657  ast_queue_log(queuename, "MANAGER", membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
10658  }
10659  astman_send_ack(s, m, "Added interface to queue");
10660  break;
10661  case RES_EXISTS:
10662  astman_send_error(s, m, "Unable to add interface: Already there");
10663  break;
10664  case RES_NOSUCHQUEUE:
10665  astman_send_error(s, m, "Unable to add interface to queue: No such queue");
10666  break;
10667  case RES_OUTOFMEMORY:
10668  astman_send_error(s, m, "Out of memory");
10669  break;
10670  }
10671 
10672  return 0;
10673 }
10674 
10675 static int manager_remove_queue_member(struct mansession *s, const struct message *m)
10676 {
10677  const char *queuename, *interface;
10678  struct member *mem = NULL;
10679 
10680  queuename = astman_get_header(m, "Queue");
10681  interface = astman_get_header(m, "Interface");
10682 
10683  if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) {
10684  astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters.");
10685  return 0;
10686  }
10687 
10688  if (log_membername_as_agent) {
10689  mem = find_member_by_queuename_and_interface(queuename, interface);
10690  }
10691 
10692  switch (remove_from_queue(queuename, interface)) {
10693  case RES_OKAY:
10694  if (!mem || ast_strlen_zero(mem->membername)) {
10695  ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
10696  } else {
10697  ast_queue_log(queuename, "MANAGER", mem->membername, "REMOVEMEMBER", "%s", "");
10698  }
10699  astman_send_ack(s, m, "Removed interface from queue");
10700  break;
10701  case RES_EXISTS:
10702  astman_send_error(s, m, "Unable to remove interface: Not there");
10703  break;
10704  case RES_NOSUCHQUEUE:
10705  astman_send_error(s, m, "Unable to remove interface from queue: No such queue");
10706  break;
10707  case RES_OUTOFMEMORY:
10708  astman_send_error(s, m, "Out of memory");
10709  break;
10710  case RES_NOT_DYNAMIC:
10711  astman_send_error(s, m, "Member not dynamic");
10712  break;
10713  }
10714 
10715  if (mem) {
10716  ao2_ref(mem, -1);
10717  }
10718 
10719  return 0;
10720 }
10721 
10722 static int manager_pause_queue_member(struct mansession *s, const struct message *m)
10723 {
10724  const char *queuename, *interface, *paused_s, *reason;
10725  int paused;
10726 
10727  interface = astman_get_header(m, "Interface");
10728  paused_s = astman_get_header(m, "Paused");
10729  queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, pause the given Interface in all queues */
10730  reason = astman_get_header(m, "Reason"); /* Optional */
10731 
10732  if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) {
10733  astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters.");
10734  return 0;
10735  }
10736 
10737  paused = abs(ast_true(paused_s));
10738 
10739  if (set_member_paused(queuename, interface, reason, paused)) {
10740  astman_send_error(s, m, "Interface not found");
10741  } else {
10742  astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
10743  }
10744  return 0;
10745 }
10746 
10747 static int manager_queue_log_custom(struct mansession *s, const struct message *m)
10748 {
10749  const char *queuename, *event, *message, *interface, *uniqueid;
10750 
10751  queuename = astman_get_header(m, "Queue");
10752  uniqueid = astman_get_header(m, "UniqueId");
10753  interface = astman_get_header(m, "Interface");
10754  event = astman_get_header(m, "Event");
10755  message = astman_get_header(m, "Message");
10756 
10757  if (ast_strlen_zero(queuename) || ast_strlen_zero(event)) {
10758  astman_send_error(s, m, "Need 'Queue' and 'Event' parameters.");
10759  return 0;
10760  }
10761 
10762  ast_queue_log(queuename, S_OR(uniqueid, "NONE"), interface, event, "%s", message);
10763  astman_send_ack(s, m, "Event added successfully");
10764 
10765  return 0;
10766 }
10767 
10768 static int manager_queue_reload(struct mansession *s, const struct message *m)
10769 {
10770  struct ast_flags mask = {0,};
10771  const char *queuename = NULL;
10772  int header_found = 0;
10773 
10774  queuename = astman_get_header(m, "Queue");
10775  if (!strcasecmp(S_OR(astman_get_header(m, "Members"), ""), "yes")) {
10776  ast_set_flag(&mask, QUEUE_RELOAD_MEMBER);
10777  header_found = 1;
10778  }
10779  if (!strcasecmp(S_OR(astman_get_header(m, "Rules"), ""), "yes")) {
10780  ast_set_flag(&mask, QUEUE_RELOAD_RULES);
10781  header_found = 1;
10782  }
10783  if (!strcasecmp(S_OR(astman_get_header(m, "Parameters"), ""), "yes")) {
10784  ast_set_flag(&mask, QUEUE_RELOAD_PARAMETERS);
10785  header_found = 1;
10786  }
10787 
10788  if (!header_found) {
10789  ast_set_flag(&mask, AST_FLAGS_ALL & ~QUEUE_RESET_STATS);
10790  }
10791 
10792  if (!reload_handler(1, &mask, queuename)) {
10793  astman_send_ack(s, m, "Queue reloaded successfully");
10794  } else {
10795  astman_send_error(s, m, "Error encountered while reloading queue");
10796  }
10797  return 0;
10798 }
10799 
10800 static int manager_queue_reset(struct mansession *s, const struct message *m)
10801 {
10802  const char *queuename = NULL;
10803  struct ast_flags mask = {QUEUE_RESET_STATS,};
10804 
10805  queuename = astman_get_header(m, "Queue");
10806 
10807  if (!reload_handler(1, &mask, queuename)) {
10808  astman_send_ack(s, m, "Queue stats reset successfully");
10809  } else {
10810  astman_send_error(s, m, "Error encountered while resetting queue stats");
10811  }
10812  return 0;
10813 }
10814 
10815 static char *complete_queue_add_member(const char *line, const char *word, int pos, int state)
10816 {
10817  /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
10818  switch (pos) {
10819  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
10820  return NULL;
10821  case 4: /* only one possible match, "to" */
10822  return state == 0 ? ast_strdup("to") : NULL;
10823  case 5: /* <queue> */
10824  return complete_queue(line, word, pos, state, 0);
10825  case 6: /* only one possible match, "penalty" */
10826  return state == 0 ? ast_strdup("penalty") : NULL;
10827  case 7:
10828  if (0 <= state && state < 100) { /* 0-99 */
10829  char *num;
10830  if ((num = ast_malloc(3))) {
10831  sprintf(num, "%d", state);
10832  }
10833  return num;
10834  } else {
10835  return NULL;
10836  }
10837  case 8: /* only one possible match, "as" */
10838  return state == 0 ? ast_strdup("as") : NULL;
10839  case 9: /* Don't attempt to complete name of member (infinite possibilities) */
10840  return NULL;
10841  default:
10842  return NULL;
10843  }
10844 }
10845 
10846 static int manager_queue_member_ringinuse(struct mansession *s, const struct message *m)
10847 {
10848  const char *queuename, *interface, *ringinuse_s;
10849  int ringinuse;
10850 
10851  interface = astman_get_header(m, "Interface");
10852  ringinuse_s = astman_get_header(m, "RingInUse");
10853 
10854  /* Optional - if not supplied, set the ringinuse value for the given Interface in all queues */
10855  queuename = astman_get_header(m, "Queue");
10856 
10857  if (ast_strlen_zero(interface) || ast_strlen_zero(ringinuse_s)) {
10858  astman_send_error(s, m, "Need 'Interface' and 'RingInUse' parameters.");
10859  return 0;
10860  }
10861 
10862  if (ast_true(ringinuse_s)) {
10863  ringinuse = 1;
10864  } else if (ast_false(ringinuse_s)) {
10865  ringinuse = 0;
10866  } else {
10867  astman_send_error(s, m, "'RingInUse' parameter must be a truth value (yes/no, on/off, 0/1, etc)");
10868  return 0;
10869  }
10870 
10871  if (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
10872  astman_send_error(s, m, "Invalid interface, queuename, or ringinuse value\n");
10873  } else {
10874  astman_send_ack(s, m, "Interface ringinuse set successfully");
10875  }
10876 
10877  return 0;
10878 }
10879 
10880 static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
10881 {
10882  const char *queuename, *interface, *penalty_s;
10883  int penalty;
10884 
10885  interface = astman_get_header(m, "Interface");
10886  penalty_s = astman_get_header(m, "Penalty");
10887  /* Optional - if not supplied, set the penalty value for the given Interface in all queues */
10888  queuename = astman_get_header(m, "Queue");
10889 
10890  if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) {
10891  astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters.");
10892  return 0;
10893  }
10894 
10895  penalty = atoi(penalty_s);
10896 
10897  if (set_member_value((char *)queuename, (char *)interface, MEMBER_PENALTY, penalty)) {
10898  astman_send_error(s, m, "Invalid interface, queuename or penalty");
10899  } else {
10900  astman_send_ack(s, m, "Interface penalty set successfully");
10901  }
10902 
10903  return 0;
10904 }
10905 
10906 static int manager_change_priority_caller_on_queue(struct mansession *s, const struct message *m)
10907 {
10908  const char *queuename, *caller, *priority_s, *immediate_s;
10909  int priority = 0, immediate = 0;
10910 
10911  queuename = astman_get_header(m, "Queue");
10912  caller = astman_get_header(m, "Caller");
10913  priority_s = astman_get_header(m, "Priority");
10914  immediate_s = astman_get_header(m, "Immediate");
10915 
10916  if (ast_strlen_zero(queuename)) {
10917  astman_send_error(s, m, "'Queue' not specified.");
10918  return 0;
10919  }
10920 
10921  if (ast_strlen_zero(caller)) {
10922  astman_send_error(s, m, "'Caller' not specified.");
10923  return 0;
10924  }
10925 
10926  if (ast_strlen_zero(priority_s)) {
10927  astman_send_error(s, m, "'Priority' not specified.");
10928  return 0;
10929  } else if (sscanf(priority_s, "%30d", &priority) != 1) {
10930  astman_send_error(s, m, "'Priority' need integer.");
10931  return 0;
10932  }
10933 
10934  if (!ast_strlen_zero(immediate_s)) {
10935  immediate = ast_true(immediate_s);
10936  }
10937 
10938  switch (change_priority_caller_on_queue(queuename, caller, priority, immediate)) {
10939  case RES_OKAY:
10940  astman_send_ack(s, m, "Priority change for caller on queue");
10941  break;
10942  case RES_NOSUCHQUEUE:
10943  astman_send_error(s, m, "Unable to change priority caller on queue: No such queue");
10944  break;
10945  case RES_NOT_CALLER:
10946  astman_send_error(s, m, "Unable to change priority caller on queue: No such caller");
10947  break;
10948  }
10949 
10950  return 0;
10951 }
10952 
10953 static int manager_request_withdraw_caller_from_queue(struct mansession *s, const struct message *m)
10954 {
10955  const char *queuename, *caller, *withdraw_info;
10956 
10957  queuename = astman_get_header(m, "Queue");
10958  caller = astman_get_header(m, "Caller");
10959  withdraw_info = astman_get_header(m, "WithdrawInfo");
10960 
10961  if (ast_strlen_zero(queuename)) {
10962  astman_send_error(s, m, "'Queue' not specified.");
10963  return 0;
10964  }
10965 
10966  if (ast_strlen_zero(caller)) {
10967  astman_send_error(s, m, "'Caller' not specified.");
10968  return 0;
10969  }
10970 
10971  switch (request_withdraw_caller_from_queue(queuename, caller, withdraw_info)) {
10972  case RES_OKAY:
10973  astman_send_ack(s, m, "Withdraw requested successfully");
10974  break;
10975  case RES_NOSUCHQUEUE:
10976  astman_send_error(s, m, "Unable to request withdraw from queue: No such queue");
10977  break;
10978  case RES_NOT_CALLER:
10979  astman_send_error(s, m, "Unable to request withdraw from queue: No such caller");
10980  break;
10981  case RES_EXISTS:
10982  astman_send_error(s, m, "Unable to request withdraw from queue: Already requested");
10983  break;
10984  }
10985 
10986  return 0;
10987 }
10988 
10989 
10990 static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
10991 {
10992  const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
10993  int penalty;
10994 
10995  switch ( cmd ) {
10996  case CLI_INIT:
10997  e->command = "queue add member";
10998  e->usage =
10999  "Usage: queue add member <dial string> to <queue> [penalty <penalty> [as <membername> [state_interface <interface>]]]\n"
11000  " Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally: a penalty, membername and a state_interface\n";
11001  return NULL;
11002  case CLI_GENERATE:
11003  return complete_queue_add_member(a->line, a->word, a->pos, a->n);
11004  }
11005 
11006  if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
11007  return CLI_SHOWUSAGE;
11008  } else if (strcmp(a->argv[4], "to")) {
11009  return CLI_SHOWUSAGE;
11010  } else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
11011  return CLI_SHOWUSAGE;
11012  } else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
11013  return CLI_SHOWUSAGE;
11014  } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
11015  return CLI_SHOWUSAGE;
11016  }
11017 
11018  queuename = a->argv[5];
11019  interface = a->argv[3];
11020  if (a->argc >= 8) {
11021  if (sscanf(a->argv[7], "%30d", &penalty) == 1) {
11022  if (penalty < 0) {
11023  ast_cli(a->fd, "Penalty must be >= 0\n");
11024  penalty = 0;
11025  }
11026  } else {
11027  ast_cli(a->fd, "Penalty must be an integer >= 0\n");
11028  penalty = 0;
11029  }
11030  } else {
11031  penalty = 0;
11032  }
11033 
11034  if (a->argc >= 10) {
11035  membername = a->argv[9];
11036  }
11037 
11038  if (a->argc >= 12) {
11039  state_interface = a->argv[11];
11040  }
11041 
11042  switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface, NULL, 0)) {
11043  case RES_OKAY:
11044  if (ast_strlen_zero(membername) || !log_membername_as_agent) {
11045  ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
11046  } else {
11047  ast_queue_log(queuename, "CLI", membername, "ADDMEMBER", "%s", "");
11048  }
11049  ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
11050  return CLI_SUCCESS;
11051  case RES_EXISTS:
11052  ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
11053  return CLI_FAILURE;
11054  case RES_NOSUCHQUEUE:
11055  ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
11056  return CLI_FAILURE;
11057  case RES_OUTOFMEMORY:
11058  ast_cli(a->fd, "Out of memory\n");
11059  return CLI_FAILURE;
11060  case RES_NOT_DYNAMIC:
11061  ast_cli(a->fd, "Member not dynamic\n");
11062  return CLI_FAILURE;
11063  default:
11064  return CLI_FAILURE;
11065  }
11066 }
11067 
11068 static char *complete_queue_remove_member(const char *line, const char *word, int pos, int state)
11069 {
11070  int which = 0;
11071  struct call_queue *q;
11072  struct member *m;
11073  struct ao2_iterator queue_iter;
11074  struct ao2_iterator mem_iter;
11075  int wordlen = strlen(word);
11076 
11077  /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
11078  if (pos > 5 || pos < 3) {
11079  return NULL;
11080  }
11081  if (pos == 4) { /* only one possible match, 'from' */
11082  return (state == 0 ? ast_strdup("from") : NULL);
11083  }
11084 
11085  if (pos == 5) { /* No need to duplicate code */
11086  return complete_queue(line, word, pos, state, 0);
11087  }
11088 
11089  /* here is the case for 3, <member> */
11090  queue_iter = ao2_iterator_init(queues, 0);
11091  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
11092  ao2_lock(q);
11093  mem_iter = ao2_iterator_init(q->members, 0);
11094  while ((m = ao2_iterator_next(&mem_iter))) {
11095  if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
11096  char *tmp;
11097  tmp = ast_strdup(m->interface);
11098  ao2_ref(m, -1);
11099  ao2_iterator_destroy(&mem_iter);
11100  ao2_unlock(q);
11101  queue_t_unref(q, "Done with iterator, returning interface name");
11102  ao2_iterator_destroy(&queue_iter);
11103  return tmp;
11104  }
11105  ao2_ref(m, -1);
11106  }
11107  ao2_iterator_destroy(&mem_iter);
11108  ao2_unlock(q);
11109  queue_t_unref(q, "Done with iterator");
11110  }
11111  ao2_iterator_destroy(&queue_iter);
11112 
11113  return NULL;
11114 }
11115 
11116 static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11117 {
11118  const char *queuename, *interface;
11119  struct member *mem = NULL;
11120  char *res = CLI_FAILURE;
11121 
11122  switch (cmd) {
11123  case CLI_INIT:
11124  e->command = "queue remove member";
11125  e->usage =
11126  "Usage: queue remove member <channel> from <queue>\n"
11127  " Remove a specific channel from a queue.\n";
11128  return NULL;
11129  case CLI_GENERATE:
11130  return complete_queue_remove_member(a->line, a->word, a->pos, a->n);
11131  }
11132 
11133  if (a->argc != 6) {
11134  return CLI_SHOWUSAGE;
11135  } else if (strcmp(a->argv[4], "from")) {
11136  return CLI_SHOWUSAGE;
11137  }
11138 
11139  queuename = a->argv[5];
11140  interface = a->argv[3];
11141 
11142  if (log_membername_as_agent) {
11143  mem = find_member_by_queuename_and_interface(queuename, interface);
11144  }
11145 
11146  switch (remove_from_queue(queuename, interface)) {
11147  case RES_OKAY:
11148  if (!mem || ast_strlen_zero(mem->membername)) {
11149  ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
11150  } else {
11151  ast_queue_log(queuename, "CLI", mem->membername, "REMOVEMEMBER", "%s", "");
11152  }
11153  ast_cli(a->fd, "Removed interface %s from queue '%s'\n", interface, queuename);
11154  res = CLI_SUCCESS;
11155  break;
11156  case RES_EXISTS:
11157  ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
11158  break;
11159  case RES_NOSUCHQUEUE:
11160  ast_cli(a->fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
11161  break;
11162  case RES_OUTOFMEMORY:
11163  ast_cli(a->fd, "Out of memory\n");
11164  break;
11165  case RES_NOT_DYNAMIC:
11166  ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Member is not dynamic\n", interface, queuename);
11167  break;
11168  }
11169 
11170  if (mem) {
11171  ao2_ref(mem, -1);
11172  }
11173 
11174  return res;
11175 }
11176 
11177 
11178 
11179 static char *handle_queue_change_priority_caller(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11180 {
11181  const char *queuename, *caller;
11182  int priority, immediate = 0;
11183  char *res = CLI_FAILURE;
11184 
11185  switch (cmd) {
11186  case CLI_INIT:
11187  e->command = "queue priority caller";
11188  e->usage =
11189  "Usage: queue priority caller <channel> on <queue> to <priority> [immediate]\n"
11190  " Change the priority of a channel on a queue, optionally applying the change in relation to existing callers.\n";
11191  return NULL;
11192  case CLI_GENERATE:
11193  return NULL;
11194  }
11195 
11196  if (a->argc < 8) {
11197  return CLI_SHOWUSAGE;
11198  } else if (strcmp(a->argv[4], "on")) {
11199  return CLI_SHOWUSAGE;
11200  } else if (strcmp(a->argv[6], "to")) {
11201  return CLI_SHOWUSAGE;
11202  } else if (sscanf(a->argv[7], "%30d", &priority) != 1) {
11203  ast_log (LOG_ERROR, "<priority> parameter must be an integer.\n");
11204  return CLI_SHOWUSAGE;
11205  } else if (a->argc == 9) {
11206  if (strcmp(a->argv[8], "immediate")) {
11207  return CLI_SHOWUSAGE;
11208  }
11209  immediate = 1;
11210  }
11211 
11212  caller = a->argv[3];
11213  queuename = a->argv[5];
11214 
11215  switch (change_priority_caller_on_queue(queuename, caller, priority, immediate)) {
11216  case RES_OKAY:
11217  res = CLI_SUCCESS;
11218  break;
11219  case RES_NOSUCHQUEUE:
11220  ast_cli(a->fd, "Unable change priority caller %s on queue '%s': No such queue\n", caller, queuename);
11221  break;
11222  case RES_NOT_CALLER:
11223  ast_cli(a->fd, "Unable to change priority caller '%s' on queue '%s': Not there\n", caller, queuename);
11224 
11225  break;
11226  }
11227 
11228  return res;
11229 }
11230 
11231 
11232 
11233 static char *complete_queue_pause_member(const char *line, const char *word, int pos, int state)
11234 {
11235  /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
11236  switch (pos) {
11237  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
11238  return NULL;
11239  case 4: /* only one possible match, "queue" */
11240  return state == 0 ? ast_strdup("queue") : NULL;
11241  case 5: /* <queue> */
11242  return complete_queue(line, word, pos, state, 0);
11243  case 6: /* "reason" */
11244  return state == 0 ? ast_strdup("reason") : NULL;
11245  case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
11246  return NULL;
11247  default:
11248  return NULL;
11249  }
11250 }
11251 
11252 static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11253 {
11254  const char *queuename, *interface, *reason;
11255  int paused;
11256 
11257  switch (cmd) {
11258  case CLI_INIT:
11259  e->command = "queue {pause|unpause} member";
11260  e->usage =
11261  "Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
11262  " Pause or unpause a queue member. Not specifying a particular queue\n"
11263  " will pause or unpause a member across all queues to which the member\n"
11264  " belongs.\n";
11265  return NULL;
11266  case CLI_GENERATE:
11267  return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
11268  }
11269 
11270  if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
11271  return CLI_SHOWUSAGE;
11272  } else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
11273  return CLI_SHOWUSAGE;
11274  } else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
11275  return CLI_SHOWUSAGE;
11276  }
11277 
11278 
11279  interface = a->argv[3];
11280  queuename = a->argc >= 6 ? a->argv[5] : NULL;
11281  reason = a->argc == 8 ? a->argv[7] : NULL;
11282  paused = !strcasecmp(a->argv[1], "pause");
11283 
11284  if (set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
11285  ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
11286  if (!ast_strlen_zero(queuename)) {
11287  ast_cli(a->fd, " in queue '%s'", queuename);
11288  }
11289  if (!ast_strlen_zero(reason)) {
11290  ast_cli(a->fd, " for reason '%s'", reason);
11291  }
11292  ast_cli(a->fd, "\n");
11293  return CLI_SUCCESS;
11294  } else {
11295  ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
11296  if (!ast_strlen_zero(queuename)) {
11297  ast_cli(a->fd, " in queue '%s'", queuename);
11298  }
11299  if (!ast_strlen_zero(reason)) {
11300  ast_cli(a->fd, " for reason '%s'", reason);
11301  }
11302  ast_cli(a->fd, "\n");
11303  return CLI_FAILURE;
11304  }
11305 }
11306 
11307 static char *complete_queue_set_member_value(const char *line, const char *word, int pos, int state)
11308 {
11309  /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
11310  switch (pos) {
11311  case 4:
11312  if (state == 0) {
11313  return ast_strdup("on");
11314  } else {
11315  return NULL;
11316  }
11317  case 6:
11318  if (state == 0) {
11319  return ast_strdup("in");
11320  } else {
11321  return NULL;
11322  }
11323  case 7:
11324  return complete_queue(line, word, pos, state, 0);
11325  default:
11326  return NULL;
11327  }
11328 }
11329 
11330 static char *handle_queue_set_member_ringinuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11331 {
11332  const char *queuename = NULL, *interface;
11333  int ringinuse;
11334 
11335  switch (cmd) {
11336  case CLI_INIT:
11337  e->command = "queue set ringinuse";
11338  e->usage =
11339  "Usage: queue set ringinuse <yes/no> on <interface> [in <queue>]\n"
11340  " Set a member's ringinuse in the queue specified. If no queue is specified\n"
11341  " then that interface's penalty is set in all queues to which that interface is a member.\n";
11342  break;
11343  return NULL;
11344  case CLI_GENERATE:
11345  return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
11346  }
11347 
11348  /* Sensible argument counts */
11349  if (a->argc != 6 && a->argc != 8) {
11350  return CLI_SHOWUSAGE;
11351  }
11352 
11353  /* Uses proper indicational words */
11354  if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
11355  return CLI_SHOWUSAGE;
11356  }
11357 
11358  /* Set the queue name if applicable */
11359  if (a->argc == 8) {
11360  queuename = a->argv[7];
11361  }
11362 
11363  /* Interface being set */
11364  interface = a->argv[5];
11365 
11366  /* Check and set the ringinuse value */
11367  if (ast_true(a->argv[3])) {
11368  ringinuse = 1;
11369  } else if (ast_false(a->argv[3])) {
11370  ringinuse = 0;
11371  } else {
11372  return CLI_SHOWUSAGE;
11373  }
11374 
11375  switch (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
11376  case RESULT_SUCCESS:
11377  ast_cli(a->fd, "Set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
11378  return CLI_SUCCESS;
11379  case RESULT_FAILURE:
11380  ast_cli(a->fd, "Failed to set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
11381  return CLI_FAILURE;
11382  default:
11383  return CLI_FAILURE;
11384  }
11385 }
11386 
11387 static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11388 {
11389  const char *queuename = NULL, *interface;
11390  int penalty = 0;
11391 
11392  switch (cmd) {
11393  case CLI_INIT:
11394  e->command = "queue set penalty";
11395  e->usage =
11396  "Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
11397  " Set a member's penalty in the queue specified. If no queue is specified\n"
11398  " then that interface's penalty is set in all queues to which that interface is a member\n";
11399  return NULL;
11400  case CLI_GENERATE:
11401  return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
11402  }
11403 
11404  if (a->argc != 6 && a->argc != 8) {
11405  return CLI_SHOWUSAGE;
11406  } else if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
11407  return CLI_SHOWUSAGE;
11408  }
11409 
11410  if (a->argc == 8) {
11411  queuename = a->argv[7];
11412  }
11413  interface = a->argv[5];
11414  penalty = atoi(a->argv[3]);
11415 
11416  switch (set_member_value(queuename, interface, MEMBER_PENALTY, penalty)) {
11417  case RESULT_SUCCESS:
11418  ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
11419  return CLI_SUCCESS;
11420  case RESULT_FAILURE:
11421  ast_cli(a->fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
11422  return CLI_FAILURE;
11423  default:
11424  return CLI_FAILURE;
11425  }
11426 }
11427 
11428 static char *complete_queue_rule_show(const char *line, const char *word, int pos, int state)
11429 {
11430  int which = 0;
11431  struct rule_list *rl_iter;
11432  int wordlen = strlen(word);
11433  char *ret = NULL;
11434  if (pos != 3) /* Wha? */ {
11435  return NULL;
11436  }
11437 
11439  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
11440  if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
11441  ret = ast_strdup(rl_iter->name);
11442  break;
11443  }
11444  }
11446 
11447  return ret;
11448 }
11449 
11450 static char *handle_queue_rule_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11451 {
11452  const char *rule;
11453  struct rule_list *rl_iter;
11454  struct penalty_rule *pr_iter;
11455  switch (cmd) {
11456  case CLI_INIT:
11457  e->command = "queue show rules";
11458  e->usage =
11459  "Usage: queue show rules [rulename]\n"
11460  " Show the list of rules associated with rulename. If no\n"
11461  " rulename is specified, list all rules defined in queuerules.conf\n";
11462  return NULL;
11463  case CLI_GENERATE:
11464  return complete_queue_rule_show(a->line, a->word, a->pos, a->n);
11465  }
11466 
11467  if (a->argc != 3 && a->argc != 4) {
11468  return CLI_SHOWUSAGE;
11469  }
11470 
11471  rule = a->argc == 4 ? a->argv[3] : "";
11473  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
11474  if (ast_strlen_zero(rule) || !strcasecmp(rl_iter->name, rule)) {
11475  ast_cli(a->fd, "Rule: %s\n", rl_iter->name);
11476  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
11477  ast_cli(a->fd, "\tAfter %d seconds, adjust QUEUE_MAX_PENALTY %s %d, adjust QUEUE_MIN_PENALTY %s %d and adjust QUEUE_RAISE_PENALTY %s %d\n", pr_iter->time, pr_iter->max_relative ? "by" : "to", pr_iter->max_value, pr_iter->min_relative ? "by" : "to", pr_iter->min_value, pr_iter->raise_relative ? "by" : "to", pr_iter->raise_value);
11478  }
11479  }
11480  }
11482  return CLI_SUCCESS;
11483 }
11484 
11485 static char *handle_queue_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11486 {
11487  struct ast_flags mask = {QUEUE_RESET_STATS,};
11488  int i;
11489 
11490  switch (cmd) {
11491  case CLI_INIT:
11492  e->command = "queue reset stats";
11493  e->usage =
11494  "Usage: queue reset stats [<queuenames>]\n"
11495  "\n"
11496  "Issuing this command will reset statistics for\n"
11497  "<queuenames>, or for all queues if no queue is\n"
11498  "specified.\n";
11499  return NULL;
11500  case CLI_GENERATE:
11501  if (a->pos >= 3) {
11502  return complete_queue(a->line, a->word, a->pos, a->n, 17);
11503  } else {
11504  return NULL;
11505  }
11506  }
11507 
11508  if (a->argc < 3) {
11509  return CLI_SHOWUSAGE;
11510  }
11511 
11512  if (a->argc == 3) {
11513  reload_handler(1, &mask, NULL);
11514  return CLI_SUCCESS;
11515  }
11516 
11517  for (i = 3; i < a->argc; ++i) {
11518  reload_handler(1, &mask, a->argv[i]);
11519  }
11520 
11521  return CLI_SUCCESS;
11522 }
11523 
11524 static char *handle_queue_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11525 {
11526  struct ast_flags mask = {0,};
11527  int i;
11528 
11529  switch (cmd) {
11530  case CLI_INIT:
11531  e->command = "queue reload {parameters|members|rules|all}";
11532  e->usage =
11533  "Usage: queue reload {parameters|members|rules|all} [<queuenames>]\n"
11534  "Reload queues. If <queuenames> are specified, only reload information pertaining\n"
11535  "to <queuenames>. One of 'parameters,' 'members,' 'rules,' or 'all' must be\n"
11536  "specified in order to know what information to reload. Below is an explanation\n"
11537  "of each of these qualifiers.\n"
11538  "\n"
11539  "\t'members' - reload queue members from queues.conf\n"
11540  "\t'parameters' - reload all queue options except for queue members\n"
11541  "\t'rules' - reload the queuerules.conf file\n"
11542  "\t'all' - reload queue rules, parameters, and members\n"
11543  "\n"
11544  "Note: the 'rules' qualifier here cannot actually be applied to a specific queue.\n"
11545  "Use of the 'rules' qualifier causes queuerules.conf to be reloaded. Even if only\n"
11546  "one queue is specified when using this command, reloading queue rules may cause\n"
11547  "other queues to be affected\n";
11548  return NULL;
11549  case CLI_GENERATE:
11550  if (a->pos >= 3) {
11551  /* find the point at which the list of queue names starts */
11552  const char *command_end = a->line + strlen("queue reload ");
11553  command_end = strchr(command_end, ' ');
11554  if (!command_end) {
11555  command_end = a->line + strlen(a->line);
11556  }
11557  return complete_queue(a->line, a->word, a->pos, a->n, command_end - a->line);
11558  } else {
11559  return NULL;
11560  }
11561  }
11562 
11563  if (a->argc < 3)
11564  return CLI_SHOWUSAGE;
11565 
11566  if (!strcasecmp(a->argv[2], "rules")) {
11567  ast_set_flag(&mask, QUEUE_RELOAD_RULES);
11568  } else if (!strcasecmp(a->argv[2], "members")) {
11569  ast_set_flag(&mask, QUEUE_RELOAD_MEMBER);
11570  } else if (!strcasecmp(a->argv[2], "parameters")) {
11571  ast_set_flag(&mask, QUEUE_RELOAD_PARAMETERS);
11572  } else if (!strcasecmp(a->argv[2], "all")) {
11573  ast_set_flag(&mask, AST_FLAGS_ALL & ~QUEUE_RESET_STATS);
11574  }
11575 
11576  if (a->argc == 3) {
11577  reload_handler(1, &mask, NULL);
11578  return CLI_SUCCESS;
11579  }
11580 
11581  for (i = 3; i < a->argc; ++i) {
11582  reload_handler(1, &mask, a->argv[i]);
11583  }
11584 
11585  return CLI_SUCCESS;
11586 }
11587 
11588 /*!
11589  * \brief Update Queue with data of an outgoing call
11590 */
11591 static int qupd_exec(struct ast_channel *chan, const char *data)
11592 {
11593  int oldtalktime;
11594  char *parse;
11595  struct call_queue *q;
11596  struct member *mem;
11597  int newtalktime = 0;
11598 
11599  AST_DECLARE_APP_ARGS(args,
11600  AST_APP_ARG(queuename);
11601  AST_APP_ARG(uniqueid);
11602  AST_APP_ARG(agent);
11603  AST_APP_ARG(status);
11604  AST_APP_ARG(talktime);
11605  AST_APP_ARG(params););
11606 
11607  if (ast_strlen_zero(data)) {
11608  ast_log(LOG_WARNING, "QueueUpdate requires arguments (queuename,uniqueid,agent,status,talktime,params[totaltime,callednumber])\n");
11609  return -1;
11610  }
11611 
11612  parse = ast_strdupa(data);
11613 
11614  AST_STANDARD_APP_ARGS(args, parse);
11615 
11616  if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid) || ast_strlen_zero(args.agent) || ast_strlen_zero(args.status)) {
11617  ast_log(LOG_WARNING, "Missing argument to QueueUpdate (queuename,uniqueid,agent,status,talktime,params[totaltime|callednumber])\n");
11618  return -1;
11619  }
11620 
11621  if (!ast_strlen_zero(args.talktime)) {
11622  newtalktime = atoi(args.talktime);
11623  }
11624 
11625  q = find_load_queue_rt_friendly(args.queuename);
11626  if (!q) {
11627  ast_log(LOG_WARNING, "QueueUpdate could not find requested queue '%s'\n", args.queuename);
11628  return 0;
11629  }
11630 
11631  ao2_lock(q);
11632  if (q->members) {
11633  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
11634  while ((mem = ao2_iterator_next(&mem_iter))) {
11635  if (!strcasecmp(mem->membername, args.agent)) {
11636  if (!strcasecmp(args.status, "ANSWER")) {
11637  oldtalktime = q->talktime;
11638  q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
11639  time(&mem->lastcall);
11640  mem->calls++;
11641  mem->lastqueue = q;
11642  q->callscompleted++;
11643 
11644  if (newtalktime <= q->servicelevel) {
11645  q->callscompletedinsl++;
11646  }
11647  } else {
11648 
11649  time(&mem->lastcall);
11650  q->callsabandoned++;
11651  }
11652 
11653  ast_queue_log(args.queuename, args.uniqueid, args.agent, "OUTCALL", "%s|%s|%s", args.status, args.talktime, args.params);
11654  }
11655 
11656  ao2_ref(mem, -1);
11657  }
11658 
11659  ao2_iterator_destroy(&mem_iter);
11660  }
11661 
11662  ao2_unlock(q);
11663  queue_t_unref(q, "Done with temporary pointer");
11664 
11665  return 0;
11666 }
11667 
11668 static struct ast_cli_entry cli_queue[] = {
11669  AST_CLI_DEFINE(queue_show, "Show status of a specified queue"),
11670  AST_CLI_DEFINE(handle_queue_rule_show, "Show the rules defined in queuerules.conf"),
11671  AST_CLI_DEFINE(handle_queue_add_member, "Add a channel to a specified queue"),
11672  AST_CLI_DEFINE(handle_queue_remove_member, "Removes a channel from a specified queue"),
11673  AST_CLI_DEFINE(handle_queue_pause_member, "Pause or unpause a queue member"),
11674  AST_CLI_DEFINE(handle_queue_set_member_penalty, "Set penalty for a channel of a specified queue"),
11675  AST_CLI_DEFINE(handle_queue_set_member_ringinuse, "Set ringinuse for a channel of a specified queue"),
11676  AST_CLI_DEFINE(handle_queue_reload, "Reload queues, members, queue rules, or parameters"),
11677  AST_CLI_DEFINE(handle_queue_reset, "Reset statistics for a queue"),
11678  AST_CLI_DEFINE(handle_queue_change_priority_caller, "Change priority caller on queue"),
11679 };
11680 
11681 static struct stasis_message_router *agent_router;
11682 static struct stasis_forward *topic_forwarder;
11683 
11684 static int unload_module(void)
11685 {
11687  agent_router = NULL;
11688 
11689  topic_forwarder = stasis_forward_cancel(topic_forwarder);
11690 
11691  STASIS_MESSAGE_TYPE_CLEANUP(queue_caller_join_type);
11692  STASIS_MESSAGE_TYPE_CLEANUP(queue_caller_leave_type);
11693  STASIS_MESSAGE_TYPE_CLEANUP(queue_caller_abandon_type);
11694 
11695  STASIS_MESSAGE_TYPE_CLEANUP(queue_member_status_type);
11696  STASIS_MESSAGE_TYPE_CLEANUP(queue_member_added_type);
11697  STASIS_MESSAGE_TYPE_CLEANUP(queue_member_removed_type);
11698  STASIS_MESSAGE_TYPE_CLEANUP(queue_member_pause_type);
11699  STASIS_MESSAGE_TYPE_CLEANUP(queue_member_penalty_type);
11700  STASIS_MESSAGE_TYPE_CLEANUP(queue_member_ringinuse_type);
11701 
11702  STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_called_type);
11703  STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_connect_type);
11704  STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_complete_type);
11705  STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_dump_type);
11706  STASIS_MESSAGE_TYPE_CLEANUP(queue_agent_ringnoanswer_type);
11707 
11708  ast_cli_unregister_multiple(cli_queue, ARRAY_LEN(cli_queue));
11709  ast_manager_unregister("QueueStatus");
11710  ast_manager_unregister("QueueRule");
11711  ast_manager_unregister("QueueSummary");
11712  ast_manager_unregister("QueueAdd");
11713  ast_manager_unregister("QueueRemove");
11714  ast_manager_unregister("QueuePause");
11715  ast_manager_unregister("QueueLog");
11716  ast_manager_unregister("QueueUpdate");
11717  ast_manager_unregister("QueuePenalty");
11718  ast_manager_unregister("QueueReload");
11719  ast_manager_unregister("QueueReset");
11720  ast_manager_unregister("QueueMemberRingInUse");
11721  ast_manager_unregister("QueueChangePriorityCaller");
11722  ast_manager_unregister("QueueWithdrawCaller");
11723  ast_unregister_application(app_aqm);
11724  ast_unregister_application(app_rqm);
11725  ast_unregister_application(app_pqm);
11726  ast_unregister_application(app_upqm);
11728  ast_unregister_application(app_qupd);
11730  ast_custom_function_unregister(&queueexists_function);
11731  ast_custom_function_unregister(&queuevar_function);
11732  ast_custom_function_unregister(&queuemembercount_function);
11733  ast_custom_function_unregister(&queuemembercount_dep);
11734  ast_custom_function_unregister(&queuememberlist_function);
11735  ast_custom_function_unregister(&queuegetchannel_function);
11736  ast_custom_function_unregister(&queuewaitingcount_function);
11737  ast_custom_function_unregister(&queuememberpenalty_function);
11738 
11739  device_state_sub = stasis_unsubscribe_and_join(device_state_sub);
11740 
11741  ast_unload_realtime("queue_members");
11742  ao2_cleanup(queues);
11743  ao2_cleanup(pending_members);
11744 
11745  queues = NULL;
11746  return 0;
11747 }
11748 
11749 /*!
11750  * \brief Load the module
11751  *
11752  * Module loading including tests for configuration or dependencies.
11753  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
11754  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
11755  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
11756  * configuration file or other non-critical problem return
11757  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
11758  */
11759 static int load_module(void)
11760 {
11761  int err = 0;
11762  struct ast_flags mask = {AST_FLAGS_ALL, };
11763  struct ast_config *member_config;
11764  struct stasis_topic *queue_topic;
11765  struct stasis_topic *manager_topic;
11766 
11767  queues = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MAX_QUEUE_BUCKETS,
11768  queue_hash_cb, NULL, queue_cmp_cb);
11769  if (!queues) {
11770  return AST_MODULE_LOAD_DECLINE;
11771  }
11772 
11774  MAX_CALL_ATTEMPT_BUCKETS, pending_members_hash, NULL, pending_members_cmp);
11775  if (!pending_members) {
11776  unload_module();
11777  return AST_MODULE_LOAD_DECLINE;
11778  }
11779 
11780  use_weight = 0;
11781 
11782  if (reload_handler(0, &mask, NULL)) {
11783  unload_module();
11784  return AST_MODULE_LOAD_DECLINE;
11785  }
11786 
11787  ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, "reason_paused", RQ_CHAR, 80, SENTINEL);
11788 
11789  /*
11790  * This section is used to determine which name for 'ringinuse' to use in realtime members
11791  * Necessary for supporting older setups.
11792  *
11793  * It also checks if 'reason_paused' exists in the realtime backend
11794  */
11795  member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
11796  if (!member_config) {
11797  realtime_ringinuse_field = "ringinuse";
11798  } else {
11799  const char *config_val;
11800 
11801  if ((config_val = ast_variable_retrieve(member_config, NULL, "ringinuse"))) {
11802  ast_log(LOG_NOTICE, "ringinuse field entries found in queue_members table. Using 'ringinuse'\n");
11803  realtime_ringinuse_field = "ringinuse";
11804  } else if ((config_val = ast_variable_retrieve(member_config, NULL, "ignorebusy"))) {
11805  ast_log(LOG_NOTICE, "ignorebusy field found in queue_members table with no ringinuse field. Using 'ignorebusy'\n");
11806  realtime_ringinuse_field = "ignorebusy";
11807  } else {
11808  ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
11809  realtime_ringinuse_field = "ringinuse";
11810  }
11811 
11812  if (ast_variable_retrieve(member_config, NULL, "reason_paused")) {
11813  realtime_reason_paused = 1;
11814  }
11815  }
11816  ast_config_destroy(member_config);
11817 
11818  if (queue_persistent_members) {
11820  }
11821 
11822  err |= ast_cli_register_multiple(cli_queue, ARRAY_LEN(cli_queue));
11824  err |= ast_register_application_xml(app_aqm, aqm_exec);
11825  err |= ast_register_application_xml(app_rqm, rqm_exec);
11826  err |= ast_register_application_xml(app_pqm, pqm_exec);
11827  err |= ast_register_application_xml(app_upqm, upqm_exec);
11828  err |= ast_register_application_xml(app_ql, ql_exec);
11829  err |= ast_register_application_xml(app_qupd, qupd_exec);
11830  err |= ast_manager_register_xml("QueueStatus", 0, manager_queues_status);
11831  err |= ast_manager_register_xml("QueueSummary", 0, manager_queues_summary);
11832  err |= ast_manager_register_xml("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member);
11833  err |= ast_manager_register_xml("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member);
11834  err |= ast_manager_register_xml("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member);
11835  err |= ast_manager_register_xml("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom);
11836  err |= ast_manager_register_xml("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty);
11837  err |= ast_manager_register_xml("QueueMemberRingInUse", EVENT_FLAG_AGENT, manager_queue_member_ringinuse);
11838  err |= ast_manager_register_xml("QueueRule", 0, manager_queue_rule_show);
11839  err |= ast_manager_register_xml("QueueReload", 0, manager_queue_reload);
11840  err |= ast_manager_register_xml("QueueReset", 0, manager_queue_reset);
11841  err |= ast_manager_register_xml("QueueChangePriorityCaller", 0, manager_change_priority_caller_on_queue);
11842  err |= ast_manager_register_xml("QueueWithdrawCaller", 0, manager_request_withdraw_caller_from_queue);
11843  err |= ast_custom_function_register(&queuevar_function);
11844  err |= ast_custom_function_register(&queueexists_function);
11845  err |= ast_custom_function_register(&queuemembercount_function);
11846  err |= ast_custom_function_register(&queuemembercount_dep);
11847  err |= ast_custom_function_register(&queuememberlist_function);
11848  err |= ast_custom_function_register(&queuegetchannel_function);
11849  err |= ast_custom_function_register(&queuewaitingcount_function);
11850  err |= ast_custom_function_register(&queuememberpenalty_function);
11851 
11852  /* in the following subscribe call, do I use DEVICE_STATE, or DEVICE_STATE_CHANGE? */
11853  device_state_sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL);
11854  if (!device_state_sub) {
11855  err = -1;
11856  }
11859 
11860  manager_topic = ast_manager_get_topic();
11861  queue_topic = ast_queue_topic_all();
11862  if (!manager_topic || !queue_topic) {
11863  unload_module();
11864  return AST_MODULE_LOAD_DECLINE;
11865  }
11866  topic_forwarder = stasis_forward_all(queue_topic, manager_topic);
11867  if (!topic_forwarder) {
11868  unload_module();
11869  return AST_MODULE_LOAD_DECLINE;
11870  }
11871 
11874  unload_module();
11875  return AST_MODULE_LOAD_DECLINE;
11876  }
11877  agent_router = stasis_message_router_create(ast_channel_topic_all());
11878  if (!agent_router) {
11879  unload_module();
11880  return AST_MODULE_LOAD_DECLINE;
11881  }
11882  err |= stasis_message_router_add(agent_router,
11884  queue_agent_cb,
11885  NULL);
11886  err |= stasis_message_router_add(agent_router,
11888  queue_agent_cb,
11889  NULL);
11890 
11891  err |= STASIS_MESSAGE_TYPE_INIT(queue_caller_join_type);
11892  err |= STASIS_MESSAGE_TYPE_INIT(queue_caller_leave_type);
11893  err |= STASIS_MESSAGE_TYPE_INIT(queue_caller_abandon_type);
11894 
11895  err |= STASIS_MESSAGE_TYPE_INIT(queue_member_status_type);
11896  err |= STASIS_MESSAGE_TYPE_INIT(queue_member_added_type);
11897  err |= STASIS_MESSAGE_TYPE_INIT(queue_member_removed_type);
11898  err |= STASIS_MESSAGE_TYPE_INIT(queue_member_pause_type);
11899  err |= STASIS_MESSAGE_TYPE_INIT(queue_member_penalty_type);
11900  err |= STASIS_MESSAGE_TYPE_INIT(queue_member_ringinuse_type);
11901 
11902  err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_called_type);
11903  err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_connect_type);
11904  err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_complete_type);
11905  err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_dump_type);
11906  err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_ringnoanswer_type);
11907 
11908  if (err) {
11909  unload_module();
11910  return AST_MODULE_LOAD_DECLINE;
11911  }
11912  return AST_MODULE_LOAD_SUCCESS;
11913 }
11914 
11915 static int reload(void)
11916 {
11917  struct ast_flags mask = {AST_FLAGS_ALL & ~QUEUE_RESET_STATS,};
11918  ast_unload_realtime("queue_members");
11919  reload_handler(1, &mask, NULL);
11920  return 0;
11921 }
11922 
11923 /*!
11924  * \brief Find a member by looking up queuename and interface.
11925  * \return member or NULL if member not found.
11926  */
11927 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface)
11928 {
11929  struct member *mem = NULL;
11930  struct call_queue *q;
11931 
11932  if ((q = find_load_queue_rt_friendly(queuename))) {
11933  ao2_lock(q);
11934  mem = ao2_find(q->members, interface, OBJ_KEY);
11935  ao2_unlock(q);
11936  queue_t_unref(q, "Expiring temporary reference.");
11937  }
11938  return mem;
11939 }
11940 
11941 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "True Call Queueing",
11942  .support_level = AST_MODULE_SUPPORT_CORE,
11943  .load = load_module,
11944  .unload = unload_module,
11945  .reload = reload,
11946  .load_pri = AST_MODPRI_DEVSTATE_CONSUMER,
11947 );
const char * name
Definition: pbx.h:119
static int get_member_penalty(char *queuename, char *interface)
Gets members penalty.
Definition: app_queue.c:8069
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1831
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Get the total number of members in a specific queue (Deprecated)
Definition: app_queue.c:9175
struct ast_variable * next
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition: channel.c:3157
int queuepos
Definition: app_queue.c:1740
Struct containing info for an AMI event to send out.
Definition: manager.h:502
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
static void do_print(struct mansession *s, int fd, const char *str)
direct output to manager or cli with proper terminator
Definition: app_queue.c:10020
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
int servicelevel
Definition: app_queue.c:1865
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7334
struct call_queue * parent
Definition: app_queue.c:1693
void ast_channel_req_accountcodes_precious(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition: channel.c:6439
int dynamic
Definition: app_queue.c:1735
Main Channel structure associated with a channel.
Local proxy channel special access.
Music on hold handling.
ast_device_state
Device States.
Definition: devicestate.h:52
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
static struct member * create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse, int wrapuptime)
allocate space for new queue member and set fields based on parameters passed
Definition: app_queue.c:2865
static int qupd_exec(struct ast_channel *chan, const char *data)
Update Queue with data of an outgoing call.
Definition: app_queue.c:11591
static void handle_blind_transfer(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Handle a blind transfer event.
Definition: app_queue.c:6409
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1556
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
Search for best metric and add to Round Robbin queue.
Definition: app_queue.c:4970
struct ast_channel_snapshot_base * base
Asterisk locking-related definitions:
int raise_penalty
Definition: app_queue.c:1712
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3310
Asterisk main include file. File version handling, generic pbx functions.
int callsabandonedinsl
Definition: app_queue.c:1864
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
int paused
Definition: app_queue.c:1738
#define RES_OKAY
Definition: app_queue.c:1565
static int rqm_exec(struct ast_channel *chan, const char *data)
RemoveQueueMember application.
Definition: app_queue.c:8283
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char digits[AST_MAX_EXTENSION]
Definition: app_queue.c:1697
char * str
Subscriber phone number (Malloced)
Definition: channel.h:386
const ast_string_field sound_holdtime
Definition: app_queue.c:1829
void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
Set the caller id information in the Asterisk channel and generate an AMI event if the caller id name...
Definition: channel.c:7372
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3895
struct ast_channel * chan
Definition: app_queue.c:1720
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
int min_penalty
Definition: app_queue.c:1711
int wrapuptime
Definition: app_queue.c:1870
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
const ast_string_field membergosub
Definition: app_queue.c:1829
String manipulation functions.
int max_relative
Definition: app_queue.c:1780
static int load_module(void)
Load the module.
Definition: app_queue.c:11759
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
Message representing attended transfer.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct stasis_message_router * bridge_router
Definition: app_queue.c:6246
struct ast_channel_snapshot * channel
int max_penalty
Definition: app_queue.c:1710
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
int last_periodic_announce_sound
Definition: app_queue.c:1705
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
time_t start
Definition: app_queue.c:1715
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
static int force_longest_waiting_caller
queues.conf [general] option
Definition: app_queue.c:1617
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
Definition: json.c:756
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
Definition: channel.c:2045
char exten[AST_MAX_EXTENSION]
int penaltymemberslimit
Definition: app_queue.c:1871
Device state management.
Support for translation of data formats. translate.c.
static int upqm_exec(struct ast_channel *chan, const char *data)
UnpauseQueueMember application.
Definition: app_queue.c:8247
Message published during a blind transfer.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
#define MAX_MUSICCLASS
Definition: channel.h:173
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
#define OBJ_KEY
Definition: astobj2.h:1151
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
#define ANNOUNCEPOSITION_NO
Definition: app_queue.c:1787
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:527
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
Definition: pbx.c:3856
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1730
struct ast_json * blob
void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Indicate that the redirecting id has changed.
Definition: channel.c:10284
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY
The minimum number of seconds between position announcements.
Definition: app_queue.c:1561
unsigned int announceposition_only_up
Definition: app_queue.c:1843
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
int wrapuptime
Definition: app_queue.c:1742
struct ast_channel_snapshot * snapshot
#define OBJ_POINTER
Definition: astobj2.h:1150
static void queue_rules_set_global_params(struct ast_config *cfg)
Definition: app_queue.c:9497
int ast_channel_supports_html(struct ast_channel *channel)
Checks for HTML support on a channel.
Definition: channel.c:6623
int min_relative
Definition: app_queue.c:1781
int minannouncefrequency
Definition: app_queue.c:1854
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3467
int last_pos_said
Definition: app_queue.c:1702
descriptor for a cli entry.
Definition: cli.h:171
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
static int negative_penalty_invalid
queues.conf [general] option
Definition: app_queue.c:1611
int linwrapped
Definition: app_queue.c:1714
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:677
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
Definition: channel.c:9093
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: main/config.c:3576
int autopause
Definition: app_queue.c:1876
enum ast_device_state state
Definition: devicestate.h:248
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1569
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
time_t expire
Definition: app_queue.c:1716
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3530
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6461
Structure for variables, used for configurations and for channel variables.
struct stasis_topic * ast_queue_topic_all(void)
Get the Stasis Message Bus API topic for queue messages.
Definition: main/app.c:3344
static void queue_reset_global_params(void)
Definition: app_queue.c:9570
Structure representing a snapshot of channel state.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
static int log_membername_as_agent
queues.conf [general] option
Definition: app_queue.c:1614
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
static int queue_function_exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Check if a given queue exists.
Definition: app_queue.c:8968
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
Calculate the metric of each member in the outgoing callattempts.
Definition: app_queue.c:6044
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Definition: aoc.c:307
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1077
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static int reload_queue_rules(int reload)
Reload the rules defined in queuerules.conf.
Definition: app_queue.c:9511
char * str
Subscriber name (Malloced)
Definition: channel.h:264
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4653
Definition: astman.c:222
Dialing API.
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
Definition: main/db.c:437
char interface[256]
Definition: app_queue.c:1673
const ast_string_field uniqueid
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static char * __queues_show(struct mansession *s, int fd, int argc, const char *const *argv)
Show queue(s) status and statistics.
Definition: app_queue.c:10138
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
const char * ast_hangup_cause_to_dial_status(int hangup_cause)
Convert a hangup cause to a publishable dial status.
Definition: dial.c:749
int periodicannouncestartdelay
Definition: app_queue.c:1855
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
int log_restricted_caller_id
Definition: app_queue.c:1885
static void reload_single_member(const char *memberdata, struct call_queue *q)
reload information pertaining to a single member
Definition: app_queue.c:9617
int realtime
Definition: app_queue.c:1736
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
int ast_start_mixmonitor(struct ast_channel *chan, const char *filename, const char *options)
Start a mixmonitor on a channel with the given parameters.
Definition: mixmonitor.c:74
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
static void set_queue_result(struct ast_channel *chan, enum queue_result res)
sets the QUEUESTATUS channel variable
Definition: app_queue.c:1910
static int queue_function_memberpenalty_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty.
Definition: app_queue.c:9380
char bridge[AST_UUID_STR_LEN]
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
unsigned int dead
Definition: app_queue.c:1748
static int say_periodic_announcement(struct queue_ent *qe, int ringing)
Playback announcement to queued members if period has elapsed.
Definition: app_queue.c:5018
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1644
const ast_string_field sound_thanks
Definition: app_queue.c:1829
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7422
unsigned int delme
Definition: app_queue.c:1749
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
unsigned int announce_to_first_user
Definition: app_queue.c:1834
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
struct ao2_container * members
Definition: app_queue.c:1887
struct queue_ent * head
Definition: app_queue.c:1888
#define AST_MAX_WATCHERS
Maximum number of channels we can watch at a time.
Definition: dial.c:211
char monfmt[8]
Definition: app_queue.c:1867
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3659
struct ast_bridge_channel_snapshot_pair to_transferee
int callscompletedinsl
Definition: app_queue.c:1866
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10563
void stasis_message_router_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed...
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
int announcepositionlimit
Definition: app_queue.c:1852
static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ringinuse.
Definition: app_queue.c:9112
static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
Change queue penalty by adding rule.
Definition: app_queue.c:3083
static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config)
Find rt member record to update otherwise create one.
Definition: app_queue.c:3578
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate...
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
char membername[80]
Definition: app_queue.c:1732
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1727
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4190
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj...
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
#define RES_OUTOFMEMORY
Definition: app_queue.c:1567
Utility functions.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
Blob of data associated with a channel.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6354
const char * source_chan_uniqueid
Definition: app_queue.c:6200
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
Definition: manager.c:1981
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Number structure.
Definition: app_followme.c:154
const struct ast_channel_tech * tech
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static struct callattempt * wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
Wait for a member to answer the call.
Definition: app_queue.c:5205
int holdtime
Definition: app_queue.c:1860
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
static int queue_function_var(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
create interface var with all queue details.
Definition: app_queue.c:8924
static int queue_function_memberpenalty_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty.
Definition: app_queue.c:9412
struct ast_bridge_channel_snapshot_pair to_transfer_target
Configuration File Parser.
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2368
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
#define RES_NOT_CALLER
Definition: app_queue.c:1570
struct ast_bridge_snapshot * bridge
static char * realtime_ringinuse_field
name of the ringinuse field in the realtime database
Definition: app_queue.c:1620
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
enum ast_transfer_result result
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
Definition: utils.c:2343
const char * predial_callee
Definition: app_queue.c:1698
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: extconf.c:4172
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
Generic Advice of Charge encode and decode routines.
#define ast_config_load(filename, flags)
Load a config file.
const ast_string_field sound_minute
Definition: app_queue.c:1829
struct ast_party_connected_line connected
Definition: app_queue.c:1677
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6720
struct queue_ent::@51 qe_rules
struct ast_aoc_decoded * ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
decodes an encoded aoc payload.
Definition: aoc.c:449
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
Configure a queue parameter.
Definition: app_queue.c:3332
ast_mutex_t lock
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:427
int periodicannouncefrequency
Definition: app_queue.c:1856
General Asterisk PBX channel definitions.
struct call_queue * queue
Definition: app_queue.c:6232
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: main/config.c:3549
time_t lastpause
Definition: app_queue.c:1745
int penalty
Definition: app_queue.c:1733
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3475
struct ast_channel_snapshot * links[2]
static int pqm_exec(struct ast_channel *chan, const char *data)
PauseQueueMember application.
Definition: app_queue.c:8211
int memberdelay
Definition: app_queue.c:1882
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
static char * complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
Check if a given word is in a space-delimited list.
Definition: app_queue.c:10309
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
struct member * member
Definition: app_queue.c:6234
struct ast_aoc_encoded * ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
encodes a decoded aoc structure so it can be passed on the wire
Definition: aoc.c:650
unsigned int block_connected_update
Definition: app_queue.c:1681
const ast_string_field sound_thereare
Definition: app_queue.c:1829
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
int ring_when_ringing
Definition: app_queue.c:1703
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
static void free_members(struct call_queue *q, int all)
Iterate through queue's member list and delete them.
Definition: app_queue.c:3696
static void ringing(struct ast_channel *chan)
Helper method to send a ringing indication to a channel in a bridge.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define AST_MAX_EXTENSION
Definition: channel.h:134
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
const ast_string_field context
Definition: app_queue.c:1829
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
update the queue status
Definition: app_queue.c:5972
int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame)
Run a redirecting interception subroutine and update a channel's redirecting information.
Definition: channel.c:10383
Structure representing relevant data during a local channel optimization.
Definition: app_queue.c:6198
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
static struct member * find_member_by_queuename_and_interface(const char *queuename, const char *interface)
Find a member by looking up queuename and interface.
Definition: app_queue.c:11927
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1644
bridge configuration
Definition: channel.h:1076
void * end_bridge_callback_data
Definition: channel.h:1091
Caller Party information.
Definition: channel.h:418
structure to hold extensions
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1785
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:10003
const ast_string_field sound_next
Definition: app_queue.c:1829
int valid_digits
Definition: app_queue.c:1699
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
Definition: app_queue.c:4885
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
struct stasis_message_type * ast_channel_agent_login_type(void)
Message type for agent login on a channel.
struct ast_bridge_snapshot * bridge
#define ast_debug(level,...)
Log a DEBUG message.
static void queue_set_global_params(struct ast_config *cfg)
Definition: app_queue.c:9582
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
struct call_queue * lastqueue
Definition: app_queue.c:1747
unsigned int id
Definition: app_queue.c:6204
struct stasis_message_type * ast_channel_agent_logoff_type(void)
Message type for agent logoff on a channel.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:465
Blob of data associated with a bridge.
#define ANNOUNCEPOSITION_MORE_THAN
Definition: app_queue.c:1788
static void rna(int rnatime, struct queue_ent *qe, struct ast_channel *peer, char *interface, char *membername, int autopause)
RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer...
Definition: app_queue.c:5110
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
int linpos
Definition: app_queue.c:1713
const ast_string_field member_uniqueid
Definition: app_queue.c:6230
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
int ast_pre_call(struct ast_channel *chan, const char *sub_args)
Execute a Gosub call on the channel before a call is placed.
Definition: channel.c:6444
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition: channel.c:6434
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
Core PBX routines and definitions.
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1691
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
char moh[MAX_MUSICCLASS]
Definition: app_queue.c:1694
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:291
int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags)
Bridge a call, and add additional flags to the bridge.
Definition: features.c:595
struct ast_channel_snapshot_caller * caller
enum ast_attended_transfer_dest_type dest_type
static int num_available_members(struct call_queue *q)
Get the number of members available to accept a call.
Definition: app_queue.c:4509
static void handle_attended_transfer(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Handle an attended transfer event.
Definition: app_queue.c:6468
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
static int montype_default
queues.conf [general] option
Definition: app_queue.c:1599
int ast_channel_has_role(struct ast_channel *channel, const char *role_name)
Check if a role exists on a channel.
Definition: bridge_roles.c:394
struct stasis_message_type * ast_local_optimization_end_type(void)
Message type for when a local channel optimization completes.
static void leave_queue(struct queue_ent *qe)
Caller leaving queue.
Definition: app_queue.c:4372
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8057
static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
Part 2 of ring_one.
Definition: app_queue.c:4753
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:225
We define a custom "local user" structure because we use it not only for keeping track of what is in ...
Definition: app_queue.c:1669
static void destroy_queue(void *obj)
Free queue's member list then its string fields.
Definition: app_queue.c:3712
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
Definition: channel.c:8785
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3622
static int autofill_default
queues.conf [general] option
Definition: app_queue.c:1596
const ast_string_field bridge_uniqueid
Definition: app_queue.c:6230
int raise_relative
Definition: app_queue.c:1782
static int request_withdraw_caller_from_queue(const char *queuename, const char *caller, const char *withdraw_info)
Request to withdraw a caller from a queue.
Definition: app_queue.c:7722
struct stasis_message_router * channel_router
Definition: app_queue.c:6248
static int get_wrapuptime(struct call_queue *q, struct member *member)
Return wrapuptime.
Definition: app_queue.c:1991
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Definition: channel.c:1999
Support for dynamic strings.
Definition: strings.h:623
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
char * orig_chan_name
Definition: app_queue.c:1688
#define ANNOUNCEPOSITION_YES
Definition: app_queue.c:1786
int autopausedelay
Definition: app_queue.c:1877
static int word_in_list(const char *list, const char *word)
Check if a given word is in a space-delimited list.
Definition: app_queue.c:10250
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:610
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame)
Run a connected line interception subroutine and update a channel's connected line information...
Definition: channel.c:10338
const ast_string_field name
Definition: app_queue.c:1829
Channel datastore data for max forwards.
Definition: max_forwards.c:29
void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update)
Set the connected line information based on another connected line source.
Definition: channel.c:2054
int autofill
Definition: app_queue.c:1883
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:2728
static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Get number either busy / free / ready or total members of a specific queue.
Definition: app_queue.c:9010
Connected Line/Party information.
Definition: channel.h:456
unsigned int pending_connected_update
Definition: app_queue.c:1679
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data)
Parse and set multiple channel variables, where the pairs are separated by the ',' character...
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7766
int talktime
Definition: app_queue.c:1861
const ast_string_field caller_uniqueid
Definition: app_queue.c:6230
char context[AST_MAX_CONTEXT]
struct local_optimization caller_optimize
Definition: app_queue.c:6250
time_t last_pos
Definition: app_queue.c:1706
static int ql_exec(struct ast_channel *chan, const char *data)
QueueLog application.
Definition: app_queue.c:8435
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:522
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
static void update_status(struct call_queue *q, struct member *m, const int status)
set a member's status based on device state of that member's state_interface.
Definition: app_queue.c:2575
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8781
int roundingseconds
Definition: app_queue.c:1859
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:7485
Definition: astdb.h:31
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition: stasis.c:1174
char reason_paused[80]
Definition: app_queue.c:1739
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
set a member's status based on device state of that member's interface
Definition: app_queue.c:2641
unsigned int stop
Definition: res_smdi.c:217
int ast_channel_sendurl(struct ast_channel *channel, const char *url)
Sends a URL on a given link Send URL on link.
Definition: channel.c:6635
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
#define AST_MAX_CONTEXT
Definition: channel.h:135
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
union ast_frame::@224 data
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6771
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int state_id
Definition: app_queue.c:1731
#define AST_CHANNEL_NAME
Definition: channel.h:171
struct local_optimization member_optimize
Definition: app_queue.c:6252
const char * ast_term_reset(void)
Returns the terminal reset code.
Definition: term.c:357
static int queue_function_queuegetchannel(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_GET_CHANNEL() Get caller channel waiting at specified position in the queue...
Definition: app_queue.c:9216
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
const ast_string_field moh
Definition: app_queue.c:1829
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
Definition: aoc.c:313
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1134
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int manager_queues_status(struct mansession *s, const struct message *m)
Queue status info via AMI.
Definition: app_queue.c:10488
const char * ast_term_color(int fgcolor, int bgcolor)
Return a color sequence string.
Definition: term.c:341
const ast_string_field uniqueid
Definition: bridge.h:328
int timeoutpriority
Definition: app_queue.c:1878
const ast_string_field defaultrule
Definition: app_queue.c:1829
An API for managing task processing threads that can be shared across modules.
const ast_string_field sound_seconds
Definition: app_queue.c:1829
Basic bridge subclass API.
void ast_autoservice_chan_hangup_peer(struct ast_channel *chan, struct ast_channel *peer)
Put chan into autoservice while hanging up peer.
Definition: autoservice.c:342
struct penalty_rule * pr
Definition: app_queue.c:1722
Structure used to handle boolean flags.
Definition: utils.h:199
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1880
static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
The waiting areas for callers who are not actively calling members.
Definition: app_queue.c:5884
int pending
Definition: app_queue.c:1709
static int manager_queues_summary(struct mansession *s, const struct message *m)
Summary of queue info via the AMI.
Definition: app_queue.c:10406
time_t starttime
Definition: app_queue.c:1743
struct call_queue::@54 rules
const char * usage
Definition: cli.h:177
int randomperiodicannounce
Definition: app_queue.c:1858
int calls
Definition: app_queue.c:1734
unsigned int withdraw
Definition: app_queue.c:1718
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue.
Definition: app_queue.c:9332
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1568
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
int status
Definition: app_queue.c:1737
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
static int change_priority_caller_on_queue(const char *queuename, const char *caller, int priority, int immediate)
Change priority caller into a queue.
Definition: app_queue.c:7646
const ast_string_field announce
Definition: app_queue.c:1829
const ast_string_field sound_reporthold
Definition: app_queue.c:1829
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
Assume that the ao2_container is already locked.
Definition: astobj2.h:1852
struct stasis_message_type * ast_local_optimization_begin_type(void)
Message type for when a local channel optimization begins.
STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type)
A message type used to synchronize with the CDR topic.
int callsabandoned
Definition: app_queue.c:1863
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.
int transit_network_select
Transit Network Select.
Definition: channel.h:397
#define ANNOUNCEPOSITION_LIMIT
Definition: app_queue.c:1789
static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
Search for best metric and add to Linear queue.
Definition: app_queue.c:4994
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2179
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2031
static void record_abandoned(struct queue_ent *qe)
Record that a caller gave up on waiting in queue.
Definition: app_queue.c:5079
static void send_agent_complete(const char *queuename, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const struct member *member, time_t holdstart, time_t callstart, enum agent_complete_reason rsn)
Send out AMI message with member call completion status information.
Definition: app_queue.c:6129
const ast_string_field sound_calls
Definition: app_queue.c:1829
After Bridge Execution API.
static int realtime_rules
queuerules.conf [general] option
Definition: app_queue.c:1605
int numperiodicannounce
Definition: app_queue.c:1857
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8235
Standard Command Line Interface.
static struct call_queue * find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
Reload a single queue via realtime.
Definition: app_queue.c:3751
time_t last_periodic_announce_time
Definition: app_queue.c:1704
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
static void queue_rules_reset_global_params(void)
Definition: app_queue.c:9491
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8293
char rt_uniqueid[80]
Definition: app_queue.c:1750
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Uses hint and devicestate callback to get the state of an extension.
Definition: pbx.c:3170
static void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
Insert the 'new' entry after the 'prev' entry of queue 'q'.
Definition: app_queue.c:2089
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
ast_app: A registered application
Definition: pbx_app.c:45
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2122
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, int raise_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
Definition: app_queue.c:2422
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: utils.c:2216
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
char * withdraw_info
Definition: app_queue.c:1719
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1840
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:2063
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1129
static int realtime_reason_paused
does realtime backend support reason_paused
Definition: app_queue.c:1623
A multi channel blob data structure for multi_channel_blob stasis messages.
static int aqm_exec(struct ast_channel *chan, const char *data)
AddQueueMember application.
Definition: app_queue.c:8354
static void hangupcalls(struct queue_ent *qe, struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
Hang up a list of outgoing calls.
Definition: app_queue.c:4469
struct ast_party_dialed::@206 number
Dialed/Called number.
User data for stasis subscriptions used for queue calls.
Definition: app_queue.c:6222
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1734
char state_context[AST_MAX_CONTEXT]
Definition: app_queue.c:1729
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1023
Data structure associated with a single frame of data.
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:297
Internal Asterisk hangup causes.
int stasis_message_router_set_default(struct stasis_message_router *router, stasis_subscription_cb callback, void *data)
Sets the default route of a router.
static int use_weight
Records that one or more queues use weight.
Definition: app_queue.c:1593
Abstract JSON element (object, array, string, int, ...).
#define AST_OPTION_TONE_VERIFY
static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
Reload information pertaining to a particular queue.
Definition: app_queue.c:9759
#define RES_EXISTS
Definition: app_queue.c:1566
The structure that contains device state.
Definition: devicestate.h:238
time_t logintime
Definition: app_queue.c:1746
loadable MixMonitor functionality
Definition: search.h:40
Handy terminal functions for vt* terms.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:342
Forwarding information.
Definition: stasis.c:1531
static void print_queue(struct mansession *s, int fd, struct call_queue *q)
Print a single queue to AMI or the CLI.
Definition: app_queue.c:10030
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Definition: astobj2.h:1349
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
Definition: bridge_after.c:622
struct queue_ent * next
Definition: app_queue.c:1723
static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel, const char *filename)
Playback the given filename and monitor for any dtmf interrupts.
enum ast_aoc_type ast_aoc_get_msg_type(struct ast_aoc_decoded *decoded)
get the message type, AOC-D, AOC-E, or AOC Request
Definition: aoc.c:892
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:2850
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
enum ast_frame_type frametype
static const char *const pm_family
Persistent Members astdb family.
Definition: app_queue.c:1587
static int queue_exec(struct ast_channel *chan, const char *data)
The starting point for all queue calls.
Definition: app_queue.c:8512
#define RECHECK
Definition: app_queue.c:1555
static void reload_queue_members(void)
Reload dynamic queue members persisted into the astdb.
Definition: app_queue.c:8100
const ast_string_field sound_minutes
Definition: app_queue.c:1829
char context[AST_MAX_CONTEXT]
Definition: app_queue.c:1696
Generic container type.
AO2_STRING_FIELD_SORT_FN(transport_monitor, key)
Sort function for struct transport_monitor.
static void do_hang(struct callattempt *o)
common hangup actions
Definition: app_queue.c:4627
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
const ast_string_field queue_quantity2
Definition: app_queue.c:1829
Search option field mask.
Definition: astobj2.h:1072
static void init_queue(struct call_queue *q)
Initialize Queue default values.
Definition: app_queue.c:2949
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
int handled
Definition: app_queue.c:1708
int cancel_answered_elsewhere
Definition: app_queue.c:1717
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:599
static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue.
Definition: app_queue.c:9295
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition: stasis.c:1578
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
Definition: pbx.c:3823
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
static int remove_from_queue(const char *queuename, const char *interface)
Remove member from queue.
Definition: app_queue.c:7540
struct stasis_topic * ast_queue_topic(const char *queuename)
Get the Stasis Message Bus API topic for queue messages for a particular queue name.
Definition: main/app.c:3349
unsigned int ringinuse
Definition: app_queue.c:1751
static void copy_rules(struct queue_ent *qe, const char *rulename)
Copy rule from global list into specified queue.
Definition: app_queue.c:8469
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
struct stasis_message_type * ast_channel_hangup_request_type(void)
Message type for when a hangup is requested on a channel.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
static void update_qe_rule(struct queue_ent *qe)
update rules for queues
Definition: app_queue.c:5794
Say numbers and dates (maybe words one day too)
int callcompletedinsl
Definition: app_queue.c:1741
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
unsigned int dial_callerid_absent
Definition: app_queue.c:1683
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
const ast_string_field queue_quantity1
Definition: app_queue.c:1829
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
Asterisk module definitions.
static int is_our_turn(struct queue_ent *qe)
Check if we should start attempting to call queue members.
Definition: app_queue.c:5745
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
struct stasis_message_type * ast_channel_masquerade_type(void)
Message type for when a channel is being masqueraded.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
static struct stasis_subscription * device_state_sub
Subscription to device state change messages.
Definition: app_queue.c:1608
int callscompleted
Definition: app_queue.c:1862
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
Definition: app_queue.c:4172
static int shared_lastcall
queues.conf [general] option
Definition: app_queue.c:1602
Persistent data storage (akin to *doze registry)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
ast_context: An extension context
Definition: pbx.c:284
const ast_string_field sound_callerannounce
Definition: app_queue.c:1829
int announcefrequency
Definition: app_queue.c:1853
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
enum ast_transfer_result result
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
time_t lastcall
Definition: app_queue.c:1744
unsigned int stillgoing
Definition: app_queue.c:1685
char announce[PATH_MAX]
Definition: app_queue.c:1695
static int context_included(const char *parent, const char *child)
Returns if one context includes another context.
Definition: app_queue.c:2777
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface, const char *reason_paused, int wrapuptime)
Add member to queue.
Definition: app_queue.c:7593
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1590
static int reload_queues(int reload, struct ast_flags *mask, const char *queuename)
reload the queues.conf file
Definition: app_queue.c:9916
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2135
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
static int clear_stats(const char *queuename)
Facilitates resetting statistics for a queue.
Definition: app_queue.c:9973
static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
Place a call to a queue member.
Definition: app_queue.c:4910
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1728
const ast_string_field name
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
static int load_realtime_rules(void)
Load queue rules from realtime.
Definition: app_queue.c:3187
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3431
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532