2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2016, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief True call queues with optional send URL on answer
23 * \author Mark Spencer <markster@digium.com>
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>
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.
36 * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
38 * \note These features added by David C. Troy <dave@toad.net>:
39 * - Per-queue holdtime calculation
40 * - Estimated holdtime announcement
41 * - Position announcement
42 * - Abandoned/completed call counters
43 * - Failout timer passed as optional app parameter
44 * - Optional monitoring of calls, started when call is answered
46 * Patch Version 1.07 2003-12-24 01
48 * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
49 * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
51 * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
52 * by Matthew Enger <m.enger@xi.com.au>
54 * \ingroup applications
57 /*! \li \ref app_queues.c uses configuration file \ref queues.conf
58 * \addtogroup configuration_file
61 /*! \page queues.conf queues.conf
62 * \verbinclude queues.conf.sample
66 <use type="module">res_monitor</use>
67 <support_level>core</support_level>
74 #include <netinet/in.h>
77 #include "asterisk/lock.h"
78 #include "asterisk/file.h"
79 #include "asterisk/channel.h"
80 #include "asterisk/pbx.h"
81 #include "asterisk/app.h"
82 #include "asterisk/linkedlists.h"
83 #include "asterisk/module.h"
84 #include "asterisk/translate.h"
85 #include "asterisk/say.h"
86 #include "asterisk/features.h"
87 #include "asterisk/musiconhold.h"
88 #include "asterisk/cli.h"
89 #include "asterisk/manager.h"
90 #include "asterisk/config.h"
91 #include "asterisk/monitor.h"
92 #include "asterisk/utils.h"
93 #include "asterisk/causes.h"
94 #include "asterisk/astdb.h"
95 #include "asterisk/devicestate.h"
96 #include "asterisk/stringfields.h"
97 #include "asterisk/astobj2.h"
98 #include "asterisk/strings.h"
99 #include "asterisk/taskprocessor.h"
100 #include "asterisk/aoc.h"
101 #include "asterisk/callerid.h"
102 #include "asterisk/data.h"
103 #include "asterisk/term.h"
104 #include "asterisk/dial.h"
105 #include "asterisk/stasis_channels.h"
106 #include "asterisk/stasis_message_router.h"
107 #include "asterisk/bridge_after.h"
108 #include "asterisk/stasis_bridges.h"
109 #include "asterisk/core_local.h"
110 #include "asterisk/mixmonitor.h"
111 #include "asterisk/bridge_basic.h"
112 #include "asterisk/max_forwards.h"
115 * \par Please read before modifying this file.
116 * There are three locks which are regularly used
117 * throughout this file, the queue list lock, the lock
118 * for each individual queue, and the interface list lock.
119 * Please be extra careful to always lock in the following order
121 * 2) individual queue lock
122 * 3) interface list lock
123 * This order has sort of "evolved" over the lifetime of this
124 * application, but it is now in place this way, so please adhere
129 <application name="Queue" language="en_US">
131 Queue a call for a call queue.
134 <parameter name="queuename" required="true" />
135 <parameter name="options">
138 <para>Mark all calls as "answered elsewhere" when cancelled.</para>
141 <para>Continue in the dialplan if the callee hangs up.</para>
144 <para>data-quality (modem) call (minimum delay).</para>
146 <option name="F" argsep="^">
147 <argument name="context" required="false" />
148 <argument name="exten" required="false" />
149 <argument name="priority" required="true" />
150 <para>When the caller hangs up, transfer the <emphasis>called member</emphasis>
151 to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
153 <para>Any channel variables you want the called channel to inherit from the caller channel must be
154 prefixed with one or two underbars ('_').</para>
158 <para>When the caller hangs up, transfer the <emphasis>called member</emphasis> to the next priority of
159 the current extension and <emphasis>start</emphasis> execution at that location.</para>
161 <para>Any channel variables you want the called channel to inherit from the caller channel must be
162 prefixed with one or two underbars ('_').</para>
165 <para>Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>
169 <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
172 <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
175 <para>No retries on the timeout; will exit this application and
176 go to the next step.</para>
179 <para>Ignore call forward requests from queue members and do nothing
180 when they are requested.</para>
183 <para>Asterisk will ignore any connected line update requests or any redirecting party
184 update requests it may receive on this dial attempt.</para>
187 <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
190 <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
193 <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
196 <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
199 <para>Allow the <emphasis>called</emphasis> user to write the conversation to
200 disk via Monitor.</para>
203 <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
204 disk via Monitor.</para>
207 <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
208 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
211 <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
212 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
215 <para>Allow the <emphasis>called</emphasis> user to write the conversation
216 to disk via MixMonitor.</para>
219 <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
220 disk via MixMonitor.</para>
224 <parameter name="URL">
225 <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
227 <parameter name="announceoverride" />
228 <parameter name="timeout">
229 <para>Will cause the queue to fail out after a specified number of
230 seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
231 <replaceable>retry</replaceable> cycle.</para>
233 <parameter name="AGI">
234 <para>Will setup an AGI script to be executed on the calling party's channel once they are
235 connected to a queue member.</para>
237 <parameter name="macro">
238 <para>Will run a macro on the called party's channel (the queue member) once the parties are connected.</para>
240 <parameter name="gosub">
241 <para>Will run a gosub on the called party's channel (the queue member) once the parties are connected.</para>
243 <parameter name="rule">
244 <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
246 <parameter name="position">
247 <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
248 would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
249 the caller third in the queue.</para>
253 <para>In addition to transferring the call, a call may be parked and then picked
254 up by another user.</para>
255 <para>This application will return to the dialplan if the queue does not exist, or
256 any of the join options cause the caller to not enter the queue.</para>
257 <para>This application does not automatically answer and should be preceeded
258 by an application such as Answer(), Progress(), or Ringing().</para>
259 <para>This application sets the following channel variables upon completion:</para>
261 <variable name="QUEUESTATUS">
262 <para>The status of the call as a text string.</para>
263 <value name="TIMEOUT" />
264 <value name="FULL" />
265 <value name="JOINEMPTY" />
266 <value name="LEAVEEMPTY" />
267 <value name="JOINUNAVAIL" />
268 <value name="LEAVEUNAVAIL" />
269 <value name="CONTINUE" />
271 <variable name="ABANDONED">
272 <para>If the call was not answered by an agent this variable will be TRUE.</para>
273 <value name="TRUE" />
278 <ref type="application">Queue</ref>
279 <ref type="application">QueueLog</ref>
280 <ref type="application">AddQueueMember</ref>
281 <ref type="application">RemoveQueueMember</ref>
282 <ref type="application">PauseQueueMember</ref>
283 <ref type="application">UnpauseQueueMember</ref>
284 <ref type="function">QUEUE_VARIABLES</ref>
285 <ref type="function">QUEUE_MEMBER</ref>
286 <ref type="function">QUEUE_MEMBER_COUNT</ref>
287 <ref type="function">QUEUE_EXISTS</ref>
288 <ref type="function">QUEUE_GET_CHANNEL</ref>
289 <ref type="function">QUEUE_WAITING_COUNT</ref>
290 <ref type="function">QUEUE_MEMBER_LIST</ref>
291 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
294 <application name="AddQueueMember" language="en_US">
296 Dynamically adds queue members.
299 <parameter name="queuename" required="true" />
300 <parameter name="interface" />
301 <parameter name="penalty" />
302 <parameter name="options" />
303 <parameter name="membername" />
304 <parameter name="stateinterface" />
307 <para>Dynamically adds interface to an existing queue. If the interface is
308 already in the queue it will return an error.</para>
309 <para>This application sets the following channel variable upon completion:</para>
311 <variable name="AQMSTATUS">
312 <para>The status of the attempt to add a queue member as a text string.</para>
313 <value name="ADDED" />
314 <value name="MEMBERALREADY" />
315 <value name="NOSUCHQUEUE" />
320 <ref type="application">Queue</ref>
321 <ref type="application">QueueLog</ref>
322 <ref type="application">AddQueueMember</ref>
323 <ref type="application">RemoveQueueMember</ref>
324 <ref type="application">PauseQueueMember</ref>
325 <ref type="application">UnpauseQueueMember</ref>
326 <ref type="function">QUEUE_VARIABLES</ref>
327 <ref type="function">QUEUE_MEMBER</ref>
328 <ref type="function">QUEUE_MEMBER_COUNT</ref>
329 <ref type="function">QUEUE_EXISTS</ref>
330 <ref type="function">QUEUE_GET_CHANNEL</ref>
331 <ref type="function">QUEUE_WAITING_COUNT</ref>
332 <ref type="function">QUEUE_MEMBER_LIST</ref>
333 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
336 <application name="RemoveQueueMember" language="en_US">
338 Dynamically removes queue members.
341 <parameter name="queuename" required="true" />
342 <parameter name="interface" />
345 <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
346 <para>This application sets the following channel variable upon completion:</para>
348 <variable name="RQMSTATUS">
349 <value name="REMOVED" />
350 <value name="NOTINQUEUE" />
351 <value name="NOSUCHQUEUE" />
352 <value name="NOTDYNAMIC" />
355 <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
358 <ref type="application">Queue</ref>
359 <ref type="application">QueueLog</ref>
360 <ref type="application">AddQueueMember</ref>
361 <ref type="application">RemoveQueueMember</ref>
362 <ref type="application">PauseQueueMember</ref>
363 <ref type="application">UnpauseQueueMember</ref>
364 <ref type="function">QUEUE_VARIABLES</ref>
365 <ref type="function">QUEUE_MEMBER</ref>
366 <ref type="function">QUEUE_MEMBER_COUNT</ref>
367 <ref type="function">QUEUE_EXISTS</ref>
368 <ref type="function">QUEUE_GET_CHANNEL</ref>
369 <ref type="function">QUEUE_WAITING_COUNT</ref>
370 <ref type="function">QUEUE_MEMBER_LIST</ref>
371 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
374 <application name="PauseQueueMember" language="en_US">
376 Pauses a queue member.
379 <parameter name="queuename" />
380 <parameter name="interface" required="true" />
381 <parameter name="options" />
382 <parameter name="reason">
383 <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
387 <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
388 This prevents any calls from being sent from the queue to the interface until it is
389 unpaused with UnpauseQueueMember or the manager interface. If no queuename is given,
390 the interface is paused in every queue it is a member of. The application will fail if the
391 interface is not found.</para>
392 <para>This application sets the following channel variable upon completion:</para>
394 <variable name="PQMSTATUS">
395 <para>The status of the attempt to pause a queue member as a text string.</para>
396 <value name="PAUSED" />
397 <value name="NOTFOUND" />
400 <para>Example: PauseQueueMember(,SIP/3000)</para>
403 <ref type="application">Queue</ref>
404 <ref type="application">QueueLog</ref>
405 <ref type="application">AddQueueMember</ref>
406 <ref type="application">RemoveQueueMember</ref>
407 <ref type="application">PauseQueueMember</ref>
408 <ref type="application">UnpauseQueueMember</ref>
409 <ref type="function">QUEUE_VARIABLES</ref>
410 <ref type="function">QUEUE_MEMBER</ref>
411 <ref type="function">QUEUE_MEMBER_COUNT</ref>
412 <ref type="function">QUEUE_EXISTS</ref>
413 <ref type="function">QUEUE_GET_CHANNEL</ref>
414 <ref type="function">QUEUE_WAITING_COUNT</ref>
415 <ref type="function">QUEUE_MEMBER_LIST</ref>
416 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
419 <application name="UnpauseQueueMember" language="en_US">
421 Unpauses a queue member.
424 <parameter name="queuename" />
425 <parameter name="interface" required="true" />
426 <parameter name="options" />
427 <parameter name="reason">
428 <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
432 <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
433 and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
434 <para>This application sets the following channel variable upon completion:</para>
436 <variable name="UPQMSTATUS">
437 <para>The status of the attempt to unpause a queue member as a text string.</para>
438 <value name="UNPAUSED" />
439 <value name="NOTFOUND" />
442 <para>Example: UnpauseQueueMember(,SIP/3000)</para>
445 <ref type="application">Queue</ref>
446 <ref type="application">QueueLog</ref>
447 <ref type="application">AddQueueMember</ref>
448 <ref type="application">RemoveQueueMember</ref>
449 <ref type="application">PauseQueueMember</ref>
450 <ref type="application">UnpauseQueueMember</ref>
451 <ref type="function">QUEUE_VARIABLES</ref>
452 <ref type="function">QUEUE_MEMBER</ref>
453 <ref type="function">QUEUE_MEMBER_COUNT</ref>
454 <ref type="function">QUEUE_EXISTS</ref>
455 <ref type="function">QUEUE_GET_CHANNEL</ref>
456 <ref type="function">QUEUE_WAITING_COUNT</ref>
457 <ref type="function">QUEUE_MEMBER_LIST</ref>
458 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
461 <application name="QueueLog" language="en_US">
463 Writes to the queue_log file.
466 <parameter name="queuename" required="true" />
467 <parameter name="uniqueid" required="true" />
468 <parameter name="agent" required="true" />
469 <parameter name="event" required="true" />
470 <parameter name="additionalinfo" />
473 <para>Allows you to write your own events into the queue log.</para>
474 <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
477 <ref type="application">Queue</ref>
478 <ref type="application">QueueLog</ref>
479 <ref type="application">AddQueueMember</ref>
480 <ref type="application">RemoveQueueMember</ref>
481 <ref type="application">PauseQueueMember</ref>
482 <ref type="application">UnpauseQueueMember</ref>
483 <ref type="function">QUEUE_VARIABLES</ref>
484 <ref type="function">QUEUE_MEMBER</ref>
485 <ref type="function">QUEUE_MEMBER_COUNT</ref>
486 <ref type="function">QUEUE_EXISTS</ref>
487 <ref type="function">QUEUE_GET_CHANNEL</ref>
488 <ref type="function">QUEUE_WAITING_COUNT</ref>
489 <ref type="function">QUEUE_MEMBER_LIST</ref>
490 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
493 <application name="QueueUpdate" language="en_US">
495 Writes to the queue_log file for OutBound calls and updates Realtime Data.
496 Is used at h extension to be able to have all the parameters.
499 <parameter name="queuename" required="true" />
500 <parameter name="uniqueid" required="true" />
501 <parameter name="agent" required="true" />
502 <parameter name="status" required="true" />
503 <parameter name="talktime" required="true" />
504 <parameter name="params" required="false" />
507 <para>Allows you to write Outbound events into the queue log.</para>
508 <para>Example: exten => h,1,QueueUpdate(${QUEUE}, ${UNIQUEID}, ${AGENT}, ${DIALSTATUS}, ${ANSWEREDTIME}, ${DIALEDTIME} | ${DIALEDNUMBER})</para>
511 <function name="QUEUE_VARIABLES" language="en_US">
513 Return Queue information in variables.
516 <parameter name="queuename" required="true">
518 <enum name="QUEUEMAX">
519 <para>Maxmimum number of calls allowed.</para>
521 <enum name="QUEUESTRATEGY">
522 <para>The strategy of the queue.</para>
524 <enum name="QUEUECALLS">
525 <para>Number of calls currently in the queue.</para>
527 <enum name="QUEUEHOLDTIME">
528 <para>Current average hold time.</para>
530 <enum name="QUEUECOMPLETED">
531 <para>Number of completed calls for the queue.</para>
533 <enum name="QUEUEABANDONED">
534 <para>Number of abandoned calls.</para>
536 <enum name="QUEUESRVLEVEL">
537 <para>Queue service level.</para>
539 <enum name="QUEUESRVLEVELPERF">
540 <para>Current service level performance.</para>
546 <para>Makes the following queue variables available.</para>
547 <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
550 <ref type="application">Queue</ref>
551 <ref type="application">QueueLog</ref>
552 <ref type="application">AddQueueMember</ref>
553 <ref type="application">RemoveQueueMember</ref>
554 <ref type="application">PauseQueueMember</ref>
555 <ref type="application">UnpauseQueueMember</ref>
556 <ref type="function">QUEUE_VARIABLES</ref>
557 <ref type="function">QUEUE_MEMBER</ref>
558 <ref type="function">QUEUE_MEMBER_COUNT</ref>
559 <ref type="function">QUEUE_EXISTS</ref>
560 <ref type="function">QUEUE_GET_CHANNEL</ref>
561 <ref type="function">QUEUE_WAITING_COUNT</ref>
562 <ref type="function">QUEUE_MEMBER_LIST</ref>
563 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
566 <function name="QUEUE_MEMBER" language="en_US">
568 Count number of members answering a queue.
571 <parameter name="queuename" required="false" />
572 <parameter name="option" required="true">
575 <para>Returns the number of logged-in members for the specified queue.</para>
578 <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>
581 <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
584 <para>Returns the total number of members for the specified queue.</para>
586 <enum name="penalty">
587 <para>Gets or sets queue member penalty. If
588 <replaceable>queuename</replaceable> is not specified
589 when setting the penalty then the penalty is set in all queues
590 the interface is a member.</para>
593 <para>Gets or sets queue member paused status. If
594 <replaceable>queuename</replaceable> is not specified
595 when setting the paused status then the paused status is set
596 in all queues the interface is a member.</para>
598 <enum name="ringinuse">
599 <para>Gets or sets queue member ringinuse. If
600 <replaceable>queuename</replaceable> is not specified
601 when setting ringinuse then ringinuse is set
602 in all queues the interface is a member.</para>
606 <parameter name="interface" required="false" />
609 <para>Allows access to queue counts [R] and member information [R/W].</para>
610 <para><replaceable>queuename</replaceable> is required for all read operations.</para>
611 <para><replaceable>interface</replaceable> is required for all member operations.</para>
614 <ref type="application">Queue</ref>
615 <ref type="application">QueueLog</ref>
616 <ref type="application">AddQueueMember</ref>
617 <ref type="application">RemoveQueueMember</ref>
618 <ref type="application">PauseQueueMember</ref>
619 <ref type="application">UnpauseQueueMember</ref>
620 <ref type="function">QUEUE_VARIABLES</ref>
621 <ref type="function">QUEUE_MEMBER</ref>
622 <ref type="function">QUEUE_MEMBER_COUNT</ref>
623 <ref type="function">QUEUE_EXISTS</ref>
624 <ref type="function">QUEUE_GET_CHANNEL</ref>
625 <ref type="function">QUEUE_WAITING_COUNT</ref>
626 <ref type="function">QUEUE_MEMBER_LIST</ref>
627 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
630 <function name="QUEUE_MEMBER_COUNT" language="en_US">
632 Count number of members answering a queue.
635 <parameter name="queuename" required="true" />
638 <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
639 <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
642 <ref type="application">Queue</ref>
643 <ref type="application">QueueLog</ref>
644 <ref type="application">AddQueueMember</ref>
645 <ref type="application">RemoveQueueMember</ref>
646 <ref type="application">PauseQueueMember</ref>
647 <ref type="application">UnpauseQueueMember</ref>
648 <ref type="function">QUEUE_VARIABLES</ref>
649 <ref type="function">QUEUE_MEMBER</ref>
650 <ref type="function">QUEUE_MEMBER_COUNT</ref>
651 <ref type="function">QUEUE_EXISTS</ref>
652 <ref type="function">QUEUE_GET_CHANNEL</ref>
653 <ref type="function">QUEUE_WAITING_COUNT</ref>
654 <ref type="function">QUEUE_MEMBER_LIST</ref>
655 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
658 <function name="QUEUE_EXISTS" language="en_US">
660 Check if a named queue exists on this server
663 <parameter name="queuename" />
666 <para>Returns 1 if the specified queue exists, 0 if it does not</para>
669 <ref type="application">Queue</ref>
670 <ref type="application">QueueLog</ref>
671 <ref type="application">AddQueueMember</ref>
672 <ref type="application">RemoveQueueMember</ref>
673 <ref type="application">PauseQueueMember</ref>
674 <ref type="application">UnpauseQueueMember</ref>
675 <ref type="function">QUEUE_VARIABLES</ref>
676 <ref type="function">QUEUE_MEMBER</ref>
677 <ref type="function">QUEUE_MEMBER_COUNT</ref>
678 <ref type="function">QUEUE_EXISTS</ref>
679 <ref type="function">QUEUE_GET_CHANNEL</ref>
680 <ref type="function">QUEUE_WAITING_COUNT</ref>
681 <ref type="function">QUEUE_MEMBER_LIST</ref>
682 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
685 <function name="QUEUE_GET_CHANNEL" language="en_US">
687 Return caller at the specified position in a queue.
690 <parameter name="queuename" required="true" />
691 <parameter name="position" />
694 <para>Returns the caller channel at <replaceable>position</replaceable> in the specified <replaceable>queuename</replaceable>.</para>
695 <para>If <replaceable>position</replaceable> is unspecified the first channel is returned.</para>
698 <ref type="application">Queue</ref>
699 <ref type="application">QueueLog</ref>
700 <ref type="application">AddQueueMember</ref>
701 <ref type="application">RemoveQueueMember</ref>
702 <ref type="application">PauseQueueMember</ref>
703 <ref type="application">UnpauseQueueMember</ref>
704 <ref type="function">QUEUE_VARIABLES</ref>
705 <ref type="function">QUEUE_MEMBER</ref>
706 <ref type="function">QUEUE_MEMBER_COUNT</ref>
707 <ref type="function">QUEUE_EXISTS</ref>
708 <ref type="function">QUEUE_WAITING_COUNT</ref>
709 <ref type="function">QUEUE_MEMBER_LIST</ref>
710 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
713 <function name="QUEUE_WAITING_COUNT" language="en_US">
715 Count number of calls currently waiting in a queue.
718 <parameter name="queuename" />
721 <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
724 <ref type="application">Queue</ref>
725 <ref type="application">QueueLog</ref>
726 <ref type="application">AddQueueMember</ref>
727 <ref type="application">RemoveQueueMember</ref>
728 <ref type="application">PauseQueueMember</ref>
729 <ref type="application">UnpauseQueueMember</ref>
730 <ref type="function">QUEUE_VARIABLES</ref>
731 <ref type="function">QUEUE_MEMBER</ref>
732 <ref type="function">QUEUE_MEMBER_COUNT</ref>
733 <ref type="function">QUEUE_EXISTS</ref>
734 <ref type="function">QUEUE_GET_CHANNEL</ref>
735 <ref type="function">QUEUE_WAITING_COUNT</ref>
736 <ref type="function">QUEUE_MEMBER_LIST</ref>
737 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
740 <function name="QUEUE_MEMBER_LIST" language="en_US">
742 Returns a list of interfaces on a queue.
745 <parameter name="queuename" required="true" />
748 <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
751 <ref type="application">Queue</ref>
752 <ref type="application">QueueLog</ref>
753 <ref type="application">AddQueueMember</ref>
754 <ref type="application">RemoveQueueMember</ref>
755 <ref type="application">PauseQueueMember</ref>
756 <ref type="application">UnpauseQueueMember</ref>
757 <ref type="function">QUEUE_VARIABLES</ref>
758 <ref type="function">QUEUE_MEMBER</ref>
759 <ref type="function">QUEUE_MEMBER_COUNT</ref>
760 <ref type="function">QUEUE_EXISTS</ref>
761 <ref type="function">QUEUE_GET_CHANNEL</ref>
762 <ref type="function">QUEUE_WAITING_COUNT</ref>
763 <ref type="function">QUEUE_MEMBER_LIST</ref>
764 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
767 <function name="QUEUE_MEMBER_PENALTY" language="en_US">
769 Gets or sets queue members penalty.
772 <parameter name="queuename" required="true" />
773 <parameter name="interface" required="true" />
776 <para>Gets or sets queue members penalty.</para>
777 <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
780 <ref type="application">Queue</ref>
781 <ref type="application">QueueLog</ref>
782 <ref type="application">AddQueueMember</ref>
783 <ref type="application">RemoveQueueMember</ref>
784 <ref type="application">PauseQueueMember</ref>
785 <ref type="application">UnpauseQueueMember</ref>
786 <ref type="function">QUEUE_VARIABLES</ref>
787 <ref type="function">QUEUE_MEMBER</ref>
788 <ref type="function">QUEUE_MEMBER_COUNT</ref>
789 <ref type="function">QUEUE_EXISTS</ref>
790 <ref type="function">QUEUE_GET_CHANNEL</ref>
791 <ref type="function">QUEUE_WAITING_COUNT</ref>
792 <ref type="function">QUEUE_MEMBER_LIST</ref>
793 <ref type="function">QUEUE_MEMBER_PENALTY</ref>
796 <manager name="Queues" language="en_US">
803 <para>Show queues information.</para>
806 <manager name="QueueStatus" language="en_US">
811 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
812 <parameter name="Queue">
813 <para>Limit the response to the status of the specified queue.</para>
815 <parameter name="Member">
816 <para>Limit the response to the status of the specified member.</para>
820 <para>Check the status of one or more queues.</para>
823 <manager name="QueueSummary" language="en_US">
828 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
829 <parameter name="Queue">
830 <para>Queue for which the summary is requested.</para>
834 <para>Request the manager to send a QueueSummary event.</para>
837 <manager name="QueueAdd" language="en_US">
839 Add interface to queue.
842 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
843 <parameter name="Queue" required="true">
844 <para>Queue's name.</para>
846 <parameter name="Interface" required="true">
847 <para>The name of the interface (tech/name) to add to the queue.</para>
849 <parameter name="Penalty">
850 <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>
852 <parameter name="Paused">
853 <para>To pause or not the member initially (true/false or 1/0).</para>
855 <parameter name="MemberName">
856 <para>Text alias for the interface.</para>
858 <parameter name="StateInterface" />
863 <manager name="QueueRemove" language="en_US">
865 Remove interface from queue.
868 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
869 <parameter name="Queue" required="true">
870 <para>The name of the queue to take action on.</para>
872 <parameter name="Interface" required="true">
873 <para>The interface (tech/name) to remove from queue.</para>
879 <manager name="QueuePause" language="en_US">
881 Makes a queue member temporarily unavailable.
884 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
885 <parameter name="Interface" required="true">
886 <para>The name of the interface (tech/name) to pause or unpause.</para>
888 <parameter name="Paused" required="true">
889 <para>Pause or unpause the interface. Set to 'true' to pause the member or 'false' to unpause.</para>
891 <parameter name="Queue">
892 <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>
894 <parameter name="Reason">
895 <para>Text description, returned in the event QueueMemberPaused.</para>
899 <para>Pause or unpause a member in a queue.</para>
902 <manager name="QueueLog" language="en_US">
904 Adds custom entry in queue_log.
907 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
908 <parameter name="Queue" required="true" />
909 <parameter name="Event" required="true" />
910 <parameter name="Uniqueid" />
911 <parameter name="Interface" />
912 <parameter name="Message" />
917 <manager name="QueuePenalty" language="en_US">
919 Set the penalty for a queue member.
922 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
923 <parameter name="Interface" required="true">
924 <para>The interface (tech/name) of the member whose penalty to change.</para>
926 <parameter name="Penalty" required="true">
927 <para>The new penalty (number) for the member. Must be nonnegative.</para>
929 <parameter name="Queue">
930 <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>
934 <para>Change the penalty of a queue member</para>
937 <manager name="QueueMemberRingInUse" language="en_US">
939 Set the ringinuse value for a queue member.
942 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
943 <parameter name="Interface" required="true" />
944 <parameter name="RingInUse" required="true" />
945 <parameter name="Queue" />
950 <manager name="QueueRule" language="en_US">
955 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
956 <parameter name="Rule">
957 <para>The name of the rule in queuerules.conf whose contents to list.</para>
961 <para>List queue rules defined in queuerules.conf</para>
964 <manager name="QueueReload" language="en_US">
966 Reload a queue, queues, or any sub-section of a queue or queues.
969 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
970 <parameter name="Queue">
971 <para>The name of the queue to take action on. If no queue name is specified, then all queues are affected.</para>
973 <parameter name="Members">
974 <para>Whether to reload the queue's members.</para>
980 <parameter name="Rules">
981 <para>Whether to reload queuerules.conf</para>
987 <parameter name="Parameters">
988 <para>Whether to reload the other queue options.</para>
998 <manager name="QueueReset" language="en_US">
1000 Reset queue statistics.
1003 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
1004 <parameter name="Queue">
1005 <para>The name of the queue on which to reset statistics.</para>
1009 <para>Reset the statistics for a queue.</para>
1013 <managerEvent language="en_US" name="QueueMemberStatus">
1014 <managerEventInstance class="EVENT_FLAG_AGENT">
1015 <synopsis>Raised when a Queue member's status has changed.</synopsis>
1017 <parameter name="Queue">
1018 <para>The name of the queue.</para>
1020 <parameter name="MemberName">
1021 <para>The name of the queue member.</para>
1023 <parameter name="Interface">
1024 <para>The queue member's channel technology or location.</para>
1026 <parameter name="StateInterface">
1027 <para>Channel technology or location from which to read device state changes.</para>
1029 <parameter name="Membership">
1031 <enum name="dynamic"/>
1032 <enum name="realtime"/>
1033 <enum name="static"/>
1036 <parameter name="Penalty">
1037 <para>The penalty associated with the queue member.</para>
1039 <parameter name="CallsTaken">
1040 <para>The number of calls this queue member has serviced.</para>
1042 <parameter name="LastCall">
1043 <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1045 <parameter name="LastPause">
1046 <para>The time when started last paused the queue member.</para>
1048 <parameter name="InCall">
1049 <para>Set to 1 if member is in call. Set to 0 after LastCall time is updated.</para>
1055 <parameter name="Status">
1056 <para>The numeric device state status of the queue member.</para>
1058 <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
1059 <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
1060 <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
1061 <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
1062 <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
1063 <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
1064 <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
1065 <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
1066 <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
1069 <parameter name="Paused">
1075 <parameter name="PausedReason">
1076 <para>If set when paused, the reason the queue member was paused.</para>
1078 <parameter name="Ringinuse">
1085 </managerEventInstance>
1087 <managerEvent language="en_US" name="QueueMemberAdded">
1088 <managerEventInstance class="EVENT_FLAG_AGENT">
1089 <synopsis>Raised when a member is added to the queue.</synopsis>
1091 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1094 <ref type="managerEvent">QueueMemberRemoved</ref>
1095 <ref type="application">AddQueueMember</ref>
1097 </managerEventInstance>
1099 <managerEvent language="en_US" name="QueueMemberRemoved">
1100 <managerEventInstance class="EVENT_FLAG_AGENT">
1101 <synopsis>Raised when a member is removed from the queue.</synopsis>
1103 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1106 <ref type="managerEvent">QueueMemberAdded</ref>
1107 <ref type="application">RemoveQueueMember</ref>
1109 </managerEventInstance>
1111 <managerEvent language="en_US" name="QueueMemberPause">
1112 <managerEventInstance class="EVENT_FLAG_AGENT">
1113 <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
1115 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1116 <parameter name="Reason">
1117 <para>The reason a member was paused.</para>
1121 <ref type="application">PauseQueueMember</ref>
1122 <ref type="application">UnPauseQueueMember</ref>
1124 </managerEventInstance>
1126 <managerEvent language="en_US" name="QueueMemberPenalty">
1127 <managerEventInstance class="EVENT_FLAG_AGENT">
1128 <synopsis>Raised when a member's penalty is changed.</synopsis>
1130 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1133 <ref type="function">QUEUE_MEMBER</ref>
1135 </managerEventInstance>
1137 <managerEvent language="en_US" name="QueueMemberRinginuse">
1138 <managerEventInstance class="EVENT_FLAG_AGENT">
1139 <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
1141 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
1144 <ref type="function">QUEUE_MEMBER</ref>
1146 </managerEventInstance>
1148 <managerEvent language="en_US" name="QueueCallerJoin">
1149 <managerEventInstance class="EVENT_FLAG_AGENT">
1150 <synopsis>Raised when a caller joins a Queue.</synopsis>
1153 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1154 <parameter name="Position">
1155 <para>This channel's current position in the queue.</para>
1157 <parameter name="Count">
1158 <para>The total number of channels in the queue.</para>
1162 <ref type="managerEvent">QueueCallerLeave</ref>
1163 <ref type="application">Queue</ref>
1165 </managerEventInstance>
1167 <managerEvent language="en_US" name="QueueCallerLeave">
1168 <managerEventInstance class="EVENT_FLAG_AGENT">
1169 <synopsis>Raised when a caller leaves a Queue.</synopsis>
1172 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1173 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
1174 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1177 <ref type="managerEvent">QueueCallerJoin</ref>
1179 </managerEventInstance>
1181 <managerEvent language="en_US" name="QueueCallerAbandon">
1182 <managerEventInstance class="EVENT_FLAG_AGENT">
1183 <synopsis>Raised when a caller abandons the queue.</synopsis>
1186 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1187 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
1188 <parameter name="OriginalPosition">
1189 <para>The channel's original position in the queue.</para>
1191 <parameter name="HoldTime">
1192 <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1195 </managerEventInstance>
1197 <managerEvent language="en_US" name="AgentCalled">
1198 <managerEventInstance class="EVENT_FLAG_AGENT">
1199 <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
1202 <channel_snapshot prefix="Dest"/>
1203 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1204 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1205 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1208 <ref type="managerEvent">AgentRingNoAnswer</ref>
1209 <ref type="managerEvent">AgentComplete</ref>
1210 <ref type="managerEvent">AgentConnect</ref>
1212 </managerEventInstance>
1214 <managerEvent language="en_US" name="AgentRingNoAnswer">
1215 <managerEventInstance class="EVENT_FLAG_AGENT">
1216 <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
1219 <channel_snapshot prefix="Dest"/>
1220 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1221 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1222 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1223 <parameter name="RingTime">
1224 <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1228 <ref type="managerEvent">AgentCalled</ref>
1230 </managerEventInstance>
1232 <managerEvent language="en_US" name="AgentComplete">
1233 <managerEventInstance class="EVENT_FLAG_AGENT">
1234 <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
1237 <channel_snapshot prefix="Dest"/>
1238 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1239 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1240 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1241 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1242 <parameter name="TalkTime">
1243 <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
1245 <parameter name="Reason">
1247 <enum name="caller"/>
1248 <enum name="agent"/>
1249 <enum name="transfer"/>
1254 <ref type="managerEvent">AgentCalled</ref>
1255 <ref type="managerEvent">AgentConnect</ref>
1257 </managerEventInstance>
1259 <managerEvent language="en_US" name="AgentDump">
1260 <managerEventInstance class="EVENT_FLAG_AGENT">
1261 <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
1264 <channel_snapshot prefix="Dest"/>
1265 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1266 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1267 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1270 <ref type="managerEvent">AgentCalled</ref>
1271 <ref type="managerEvent">AgentConnect</ref>
1273 </managerEventInstance>
1275 <managerEvent language="en_US" name="AgentConnect">
1276 <managerEventInstance class="EVENT_FLAG_AGENT">
1277 <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
1280 <channel_snapshot prefix="Dest"/>
1281 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
1282 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
1283 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
1284 <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
1285 <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
1288 <ref type="managerEvent">AgentCalled</ref>
1289 <ref type="managerEvent">AgentComplete</ref>
1290 <ref type="managerEvent">AgentDump</ref>
1292 </managerEventInstance>
1297 OPT_MARK_AS_ANSWERED = (1 << 0),
1298 OPT_GO_ON = (1 << 1),
1299 OPT_DATA_QUALITY = (1 << 2),
1300 OPT_CALLEE_GO_ON = (1 << 3),
1301 OPT_CALLEE_HANGUP = (1 << 4),
1302 OPT_CALLER_HANGUP = (1 << 5),
1303 OPT_IGNORE_CALL_FW = (1 << 6),
1304 OPT_IGNORE_CONNECTEDLINE = (1 << 7),
1305 OPT_CALLEE_PARK = (1 << 8),
1306 OPT_CALLER_PARK = (1 << 9),
1307 OPT_NO_RETRY = (1 << 10),
1308 OPT_RINGING = (1 << 11),
1309 OPT_RING_WHEN_RINGING = (1 << 12),
1310 OPT_CALLEE_TRANSFER = (1 << 13),
1311 OPT_CALLER_TRANSFER = (1 << 14),
1312 OPT_CALLEE_AUTOMIXMON = (1 << 15),
1313 OPT_CALLER_AUTOMIXMON = (1 << 16),
1314 OPT_CALLEE_AUTOMON = (1 << 17),
1315 OPT_CALLER_AUTOMON = (1 << 18),
1319 OPT_ARG_CALLEE_GO_ON = 0,
1320 /* note: this entry _MUST_ be the last one in the enum */
1324 AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
1325 AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
1326 AST_APP_OPTION('c', OPT_GO_ON),
1327 AST_APP_OPTION('d', OPT_DATA_QUALITY),
1328 AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
1329 AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
1330 AST_APP_OPTION('H', OPT_CALLER_HANGUP),
1331 AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
1332 AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
1333 AST_APP_OPTION('k', OPT_CALLEE_PARK),
1334 AST_APP_OPTION('K', OPT_CALLER_PARK),
1335 AST_APP_OPTION('n', OPT_NO_RETRY),
1336 AST_APP_OPTION('r', OPT_RINGING),
1337 AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
1338 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1339 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
1340 AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
1341 AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
1342 AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
1343 AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
1347 QUEUE_STRATEGY_RINGALL = 0,
1348 QUEUE_STRATEGY_LEASTRECENT,
1349 QUEUE_STRATEGY_FEWESTCALLS,
1350 QUEUE_STRATEGY_RANDOM,
1351 QUEUE_STRATEGY_RRMEMORY,
1352 QUEUE_STRATEGY_LINEAR,
1353 QUEUE_STRATEGY_WRANDOM,
1354 QUEUE_STRATEGY_RRORDERED,
1358 QUEUE_AUTOPAUSE_OFF = 0,
1363 enum queue_reload_mask {
1364 QUEUE_RELOAD_PARAMETERS = (1 << 0),
1365 QUEUE_RELOAD_MEMBER = (1 << 1),
1366 QUEUE_RELOAD_RULES = (1 << 2),
1367 QUEUE_RESET_STATS = (1 << 3),
1370 static const struct strategy {
1374 { QUEUE_STRATEGY_RINGALL, "ringall" },
1375 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
1376 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
1377 { QUEUE_STRATEGY_RANDOM, "random" },
1378 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
1379 { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
1380 { QUEUE_STRATEGY_LINEAR, "linear" },
1381 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
1382 { QUEUE_STRATEGY_RRORDERED, "rrordered"},
1385 static const struct autopause {
1388 } autopausesmodes [] = {
1389 { QUEUE_AUTOPAUSE_OFF,"no" },
1390 { QUEUE_AUTOPAUSE_ON, "yes" },
1391 { QUEUE_AUTOPAUSE_ALL,"all" },
1394 #define DEFAULT_RETRY 5
1395 #define DEFAULT_TIMEOUT 15
1396 #define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
1397 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
1399 * \brief The minimum number of seconds between position announcements.
1400 * \note The default value of 15 provides backwards compatibility.
1402 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
1404 #define MAX_QUEUE_BUCKETS 53
1406 #define RES_OKAY 0 /*!< Action completed */
1407 #define RES_EXISTS (-1) /*!< Entry already exists */
1408 #define RES_OUTOFMEMORY (-2) /*!< Out of memory */
1409 #define RES_NOSUCHQUEUE (-3) /*!< No such queue */
1410 #define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
1412 static char *app = "Queue";
1414 static char *app_aqm = "AddQueueMember" ;
1416 static char *app_rqm = "RemoveQueueMember" ;
1418 static char *app_pqm = "PauseQueueMember" ;
1420 static char *app_upqm = "UnpauseQueueMember" ;
1422 static char *app_ql = "QueueLog" ;
1424 static char *app_qupd = "QueueUpdate";
1426 /*! \brief Persistent Members astdb family */
1427 static const char * const pm_family = "Queue/PersistentMembers";
1429 /*! \brief queues.conf [general] option */
1430 static int queue_persistent_members = 0;
1432 /*! \brief queues.conf per-queue weight option */
1433 static int use_weight = 0;
1435 /*! \brief queues.conf [general] option */
1436 static int autofill_default = 1;
1438 /*! \brief queues.conf [general] option */
1439 static int montype_default = 0;
1441 /*! \brief queues.conf [general] option */
1442 static int shared_lastcall = 1;
1444 /*! \brief queuesrules.conf [general] option */
1445 static int realtime_rules = 0;
1447 /*! \brief Subscription to device state change messages */
1448 static struct stasis_subscription *device_state_sub;
1450 /*! \brief queues.conf [general] option */
1451 static int update_cdr = 0;
1453 /*! \brief queues.conf [general] option */
1454 static int negative_penalty_invalid = 0;
1456 /*! \brief queues.conf [general] option */
1457 static int log_membername_as_agent = 0;
1459 /*! \brief name of the ringinuse field in the realtime database */
1460 static char *realtime_ringinuse_field;
1465 QUEUE_JOINEMPTY = 2,
1466 QUEUE_LEAVEEMPTY = 3,
1467 QUEUE_JOINUNAVAIL = 4,
1468 QUEUE_LEAVEUNAVAIL = 5,
1473 static const struct {
1474 enum queue_result id;
1476 } queue_results[] = {
1477 { QUEUE_UNKNOWN, "UNKNOWN" },
1478 { QUEUE_TIMEOUT, "TIMEOUT" },
1479 { QUEUE_JOINEMPTY,"JOINEMPTY" },
1480 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
1481 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
1482 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
1483 { QUEUE_FULL, "FULL" },
1484 { QUEUE_CONTINUE, "CONTINUE" },
1487 enum queue_timeout_priority {
1488 TIMEOUT_PRIORITY_APP,
1489 TIMEOUT_PRIORITY_CONF,
1492 /*! \brief We define a custom "local user" structure because we
1493 * use it not only for keeping track of what is in use but
1494 * also for keeping track of who we're dialing.
1496 * There are two "links" defined in this structure, q_next and call_next.
1497 * q_next links ALL defined callattempt structures into a linked list. call_next is
1498 * a link which allows for a subset of the callattempts to be traversed. This subset
1499 * is used in wait_for_answer so that irrelevant callattempts are not traversed. This
1500 * also is helpful so that queue logs are always accurate in the case where a call to
1501 * a member times out, especially if using the ringall strategy.
1504 struct callattempt {
1505 struct callattempt *q_next;
1506 struct callattempt *call_next;
1507 struct ast_channel *chan;
1508 char interface[256]; /*!< An Asterisk dial string (not a channel name) */
1511 struct call_queue *lastqueue;
1512 struct member *member;
1513 /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
1514 struct ast_party_connected_line connected;
1515 /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
1516 unsigned int pending_connected_update:1;
1517 /*! TRUE if the connected line update is blocked. */
1518 unsigned int block_connected_update:1;
1519 /*! TRUE if caller id is not available for connected line */
1520 unsigned int dial_callerid_absent:1;
1521 /*! TRUE if the call is still active */
1522 unsigned int stillgoing:1;
1523 struct ast_aoc_decoded *aoc_s_rate_list;
1524 /*! Original channel name. Must be freed. Could be NULL if allocation failed. */
1525 char *orig_chan_name;
1530 struct call_queue *parent; /*!< What queue is our parent */
1531 char moh[MAX_MUSICCLASS]; /*!< Name of musiconhold to be used */
1532 char announce[PATH_MAX]; /*!< Announcement to play for member when call is answered */
1533 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
1534 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
1535 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
1536 int pos; /*!< Where we are in the queue */
1537 int prio; /*!< Our priority */
1538 int last_pos_said; /*!< Last position we told the user */
1539 int ring_when_ringing; /*!< Should we only use ring indication when a channel is ringing? */
1540 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
1541 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
1542 time_t last_pos; /*!< Last time we told the user their position */
1543 int opos; /*!< Where we started in the queue */
1544 int handled; /*!< Whether our call was handled */
1545 int pending; /*!< Non-zero if we are attempting to call a member */
1546 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
1547 int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
1548 int linpos; /*!< If using linear strategy, what position are we at? */
1549 int linwrapped; /*!< Is the linpos wrapped? */
1550 time_t start; /*!< When we started holding */
1551 time_t expire; /*!< When this entry should expire (time out of queue) */
1552 int cancel_answered_elsewhere; /*!< Whether we should force the CAE flag on this call (C) option*/
1553 struct ast_channel *chan; /*!< Our channel */
1554 AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
1555 struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
1556 struct queue_ent *next; /*!< The next queue entry */
1560 char interface[AST_CHANNEL_NAME]; /*!< Technology/Location to dial to reach this member*/
1561 char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
1562 char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
1563 char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
1564 char membername[80]; /*!< Member name to use in queue logs */
1565 int penalty; /*!< Are we a last resort? */
1566 int calls; /*!< Number of calls serviced by this member */
1567 int dynamic; /*!< Are we dynamically added? */
1568 int realtime; /*!< Is this member realtime? */
1569 int status; /*!< Status of queue member */
1570 int paused; /*!< Are we paused (not accepting calls)? */
1571 char reason_paused[80]; /*!< Reason of paused if member is paused */
1572 int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */
1573 time_t lastcall; /*!< When last successful call was hungup */
1574 time_t lastpause; /*!< When started the last pause */
1575 unsigned int in_call:1; /*!< True if member is still in call. (so lastcall is not actual) */
1576 struct call_queue *lastqueue; /*!< Last queue we received a call */
1577 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
1578 unsigned int delme:1; /*!< Flag to delete entry on reload */
1579 char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
1580 unsigned int ringinuse:1; /*!< Flag to ring queue members even if their status is 'inuse' */
1583 enum empty_conditions {
1584 QUEUE_EMPTY_PENALTY = (1 << 0),
1585 QUEUE_EMPTY_PAUSED = (1 << 1),
1586 QUEUE_EMPTY_INUSE = (1 << 2),
1587 QUEUE_EMPTY_RINGING = (1 << 3),
1588 QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
1589 QUEUE_EMPTY_INVALID = (1 << 5),
1590 QUEUE_EMPTY_UNKNOWN = (1 << 6),
1591 QUEUE_EMPTY_WRAPUP = (1 << 7),
1594 enum member_properties {
1596 MEMBER_RINGINUSE = 1,
1599 /* values used in multi-bit flags in call_queue */
1600 #define ANNOUNCEHOLDTIME_ALWAYS 1
1601 #define ANNOUNCEHOLDTIME_ONCE 2
1602 #define QUEUE_EVENT_VARIABLES 3
1604 struct penalty_rule {
1605 int time; /*!< Number of seconds that need to pass before applying this rule */
1606 int max_value; /*!< The amount specified in the penalty rule for max penalty */
1607 int min_value; /*!< The amount specified in the penalty rule for min penalty */
1608 int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
1609 int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
1610 AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
1613 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
1614 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
1615 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
1616 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
1619 AST_DECLARE_STRING_FIELDS(
1621 AST_STRING_FIELD(name);
1622 /*! Music on Hold class */
1623 AST_STRING_FIELD(moh);
1624 /*! Announcement to play when call is answered */
1625 AST_STRING_FIELD(announce);
1627 AST_STRING_FIELD(context);
1628 /*! Macro to run upon member connection */
1629 AST_STRING_FIELD(membermacro);
1630 /*! Gosub to run upon member connection */
1631 AST_STRING_FIELD(membergosub);
1632 /*! Default rule to use if none specified in call to Queue() */
1633 AST_STRING_FIELD(defaultrule);
1634 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
1635 AST_STRING_FIELD(sound_next);
1636 /*! Sound file: "There are currently" (def. queue-thereare) */
1637 AST_STRING_FIELD(sound_thereare);
1638 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
1639 AST_STRING_FIELD(sound_calls);
1640 /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
1641 AST_STRING_FIELD(queue_quantity1);
1642 /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
1643 AST_STRING_FIELD(queue_quantity2);
1644 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
1645 AST_STRING_FIELD(sound_holdtime);
1646 /*! Sound file: "minutes." (def. queue-minutes) */
1647 AST_STRING_FIELD(sound_minutes);
1648 /*! Sound file: "minute." (def. queue-minute) */
1649 AST_STRING_FIELD(sound_minute);
1650 /*! Sound file: "seconds." (def. queue-seconds) */
1651 AST_STRING_FIELD(sound_seconds);
1652 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
1653 AST_STRING_FIELD(sound_thanks);
1654 /*! Sound file: Custom announce for caller, no default */
1655 AST_STRING_FIELD(sound_callerannounce);
1656 /*! Sound file: "Hold time" (def. queue-reporthold) */
1657 AST_STRING_FIELD(sound_reporthold);
1659 /*! Sound files: Custom announce, no default */
1660 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
1661 unsigned int dead:1;
1662 unsigned int ringinuse:1;
1663 unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
1664 unsigned int setinterfacevar:1;
1665 unsigned int setqueuevar:1;
1666 unsigned int setqueueentryvar:1;
1667 unsigned int reportholdtime:1;
1668 unsigned int wrapped:1;
1669 unsigned int timeoutrestart:1;
1670 unsigned int announceholdtime:2;
1671 unsigned int announceposition:3;
1673 unsigned int realtime:1;
1674 unsigned int found:1;
1675 unsigned int relativeperiodicannounce:1;
1676 unsigned int autopausebusy:1;
1677 unsigned int autopauseunavail:1;
1678 enum empty_conditions joinempty;
1679 enum empty_conditions leavewhenempty;
1680 int announcepositionlimit; /*!< How many positions we announce? */
1681 int announcefrequency; /*!< How often to announce their position */
1682 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
1683 int periodicannouncefrequency; /*!< How often to play periodic announcement */
1684 int numperiodicannounce; /*!< The number of periodic announcements configured */
1685 int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
1686 int roundingseconds; /*!< How many seconds do we round to? */
1687 int holdtime; /*!< Current avg holdtime, based on an exponential average */
1688 int talktime; /*!< Current avg talktime, based on the same exponential average */
1689 int callscompleted; /*!< Number of queue calls completed */
1690 int callsabandoned; /*!< Number of queue calls abandoned */
1691 int callsabandonedinsl; /*!< Number of queue calls abandoned in servicelevel */
1692 int servicelevel; /*!< seconds setting for servicelevel*/
1693 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
1694 char monfmt[8]; /*!< Format to use when recording calls */
1695 int montype; /*!< Monitor type Monitor vs. MixMonitor */
1696 int count; /*!< How many entries */
1697 int maxlen; /*!< Max number of entries */
1698 int wrapuptime; /*!< Wrapup Time */
1699 int penaltymemberslimit; /*!< Disregard penalty when queue has fewer than this many members */
1701 int retry; /*!< Retry calling everyone after this amount of time */
1702 int timeout; /*!< How long to wait for an answer */
1703 int weight; /*!< Respective weight */
1704 int autopause; /*!< Auto pause queue members if they fail to answer */
1705 int autopausedelay; /*!< Delay auto pause for autopausedelay seconds since last call */
1706 int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
1708 /* Queue strategy things */
1709 int rrpos; /*!< Round Robin - position */
1710 int memberdelay; /*!< Seconds to delay connecting member to caller */
1711 int autofill; /*!< Ignore the head call status and ring an available agent */
1713 struct ao2_container *members; /*!< Head of the list of members */
1714 struct queue_ent *head; /*!< Head of the list of callers */
1715 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
1716 AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
1721 AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
1722 AST_LIST_ENTRY(rule_list) list;
1725 static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
1727 static struct ao2_container *queues;
1729 static void update_realtime_members(struct call_queue *q);
1730 static struct member *interface_exists(struct call_queue *q, const char *interface);
1731 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
1733 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
1734 /*! \brief sets the QUEUESTATUS channel variable */
1735 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
1739 for (i = 0; i < ARRAY_LEN(queue_results); i++) {
1740 if (queue_results[i].id == res) {
1741 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
1747 static const char *int2strat(int strategy)
1751 for (x = 0; x < ARRAY_LEN(strategies); x++) {
1752 if (strategy == strategies[x].strategy) {
1753 return strategies[x].name;
1760 static int strat2int(const char *strategy)
1764 for (x = 0; x < ARRAY_LEN(strategies); x++) {
1765 if (!strcasecmp(strategy, strategies[x].name)) {
1766 return strategies[x].strategy;
1773 static int autopause2int(const char *autopause)
1776 /*This 'double check' that default value is OFF */
1777 if (ast_strlen_zero(autopause)) {
1778 return QUEUE_AUTOPAUSE_OFF;
1781 /*This 'double check' is to ensure old values works */
1782 if(ast_true(autopause)) {
1783 return QUEUE_AUTOPAUSE_ON;
1786 for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1787 if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1788 return autopausesmodes[x].autopause;
1792 /*This 'double check' that default value is OFF */
1793 return QUEUE_AUTOPAUSE_OFF;
1796 static int queue_hash_cb(const void *obj, const int flags)
1798 const struct call_queue *q = obj;
1800 return ast_str_case_hash(q->name);
1803 static int queue_cmp_cb(void *obj, void *arg, int flags)
1805 struct call_queue *q = obj, *q2 = arg;
1806 return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1810 * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
1811 * \param obj the member being acted on
1812 * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
1814 static int queue_member_decrement_followers(void *obj, void *arg, int flag)
1816 struct member *mem = obj;
1817 int *decrement_followers_after = arg;
1819 if (mem->queuepos > *decrement_followers_after) {
1827 * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
1828 * on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
1829 * \param obj member being acted on
1830 * \param arg pointer to the queue members are being removed from
1832 static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
1834 struct member *mem = obj;
1835 struct call_queue *queue = arg;
1836 int rrpos = mem->queuepos;
1839 ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &rrpos);
1846 * \brief Use this to decrement followers during removal of a member
1847 * \param queue which queue the member is being removed from
1848 * \param mem which member is being removed from the queue
1850 static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
1852 int pos = mem->queuepos;
1854 /* 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
1855 * who would have been next otherwise. */
1856 if (pos < queue->rrpos) {
1860 ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
1863 #define queue_ref(q) _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
1864 #define queue_unref(q) _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
1865 #define queue_t_ref(q, tag) _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1866 #define queue_t_unref(q, tag) _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1867 #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
1868 #define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
1870 static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
1872 __ao2_ref(q, 1, tag, file, line, filename);
1876 static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
1879 __ao2_ref(q, -1, tag, file, line, filename);
1884 /*! \brief Set variables of queue */
1885 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
1887 char interfacevar[256]="";
1892 if (q->setqueuevar) {
1894 if (q->callscompleted > 0) {
1895 sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
1898 snprintf(interfacevar, sizeof(interfacevar),
1899 "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1900 q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
1904 pbx_builtin_setvar_multiple(chan, interfacevar);
1910 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
1911 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
1913 struct queue_ent *cur;
1926 /* every queue_ent must have a reference to it's parent call_queue, this
1927 * reference does not go away until the end of the queue_ent's life, meaning
1928 * that even when the queue_ent leaves the call_queue this ref must remain. */
1931 new->pos = ++(*pos);
1935 static struct ast_manager_event_blob *queue_channel_to_ami(const char *type, struct stasis_message *message)
1937 struct ast_channel_blob *obj = stasis_message_data(message);
1938 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1939 RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1941 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1942 event_string = ast_manager_str_from_json_object(obj->blob, NULL);
1943 if (!channel_string || !event_string) {
1947 return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
1950 ast_str_buffer(channel_string),
1951 ast_str_buffer(event_string));
1954 static struct ast_manager_event_blob *queue_caller_join_to_ami(struct stasis_message *message)
1956 return queue_channel_to_ami("QueueCallerJoin", message);
1959 static struct ast_manager_event_blob *queue_caller_leave_to_ami(struct stasis_message *message)
1961 return queue_channel_to_ami("QueueCallerLeave", message);
1964 static struct ast_manager_event_blob *queue_caller_abandon_to_ami(struct stasis_message *message)
1966 return queue_channel_to_ami("QueueCallerAbandon", message);
1969 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_join_type,
1970 .to_ami = queue_caller_join_to_ami,
1972 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_leave_type,
1973 .to_ami = queue_caller_leave_to_ami,
1975 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_abandon_type,
1976 .to_ami = queue_caller_abandon_to_ami,
1979 static struct ast_manager_event_blob *queue_member_to_ami(const char *type, struct stasis_message *message)
1981 struct ast_json_payload *payload = stasis_message_data(message);
1982 RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
1984 event_string = ast_manager_str_from_json_object(payload->json, NULL);
1985 if (!event_string) {
1989 return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
1991 ast_str_buffer(event_string));
1994 static struct ast_manager_event_blob *queue_member_status_to_ami(struct stasis_message *message)
1996 return queue_member_to_ami("QueueMemberStatus", message);
1999 static struct ast_manager_event_blob *queue_member_added_to_ami(struct stasis_message *message)
2001 return queue_member_to_ami("QueueMemberAdded", message);
2004 static struct ast_manager_event_blob *queue_member_removed_to_ami(struct stasis_message *message)
2006 return queue_member_to_ami("QueueMemberRemoved", message);
2009 static struct ast_manager_event_blob *queue_member_pause_to_ami(struct stasis_message *message)
2011 return queue_member_to_ami("QueueMemberPause", message);
2014 static struct ast_manager_event_blob *queue_member_penalty_to_ami(struct stasis_message *message)
2016 return queue_member_to_ami("QueueMemberPenalty", message);
2019 static struct ast_manager_event_blob *queue_member_ringinuse_to_ami(struct stasis_message *message)
2021 return queue_member_to_ami("QueueMemberRinginuse", message);
2024 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_status_type,
2025 .to_ami = queue_member_status_to_ami,
2027 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_added_type,
2028 .to_ami = queue_member_added_to_ami,
2030 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_removed_type,
2031 .to_ami = queue_member_removed_to_ami,
2033 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_pause_type,
2034 .to_ami = queue_member_pause_to_ami,
2036 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_penalty_type,
2037 .to_ami = queue_member_penalty_to_ami,
2039 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_ringinuse_type,
2040 .to_ami = queue_member_ringinuse_to_ami,
2043 static struct ast_manager_event_blob *queue_multi_channel_to_ami(const char *type, struct stasis_message *message)
2045 struct ast_multi_channel_blob *obj = stasis_message_data(message);
2046 struct ast_channel_snapshot *caller;
2047 struct ast_channel_snapshot *agent;
2048 RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
2049 RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
2050 RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
2052 caller = ast_multi_channel_blob_get_channel(obj, "caller");
2054 caller_event_string = ast_manager_build_channel_state_string(caller);
2055 if (!caller_event_string) {
2056 ast_log(LOG_NOTICE, "No caller event string, bailing\n");
2061 agent = ast_multi_channel_blob_get_channel(obj, "agent");
2063 agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
2064 if (!agent_event_string) {
2065 ast_log(LOG_NOTICE, "No agent event string, bailing\n");
2070 event_string = ast_manager_str_from_json_object(ast_multi_channel_blob_get_json(obj), NULL);
2071 if (!event_string) {
2075 return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
2079 caller_event_string ? ast_str_buffer(caller_event_string) : "",
2080 agent_event_string ? ast_str_buffer(agent_event_string) : "",
2081 ast_str_buffer(event_string));
2084 static struct ast_manager_event_blob *queue_agent_called_to_ami(struct stasis_message *message)
2086 return queue_multi_channel_to_ami("AgentCalled", message);
2089 static struct ast_manager_event_blob *queue_agent_connect_to_ami(struct stasis_message *message)
2091 return queue_multi_channel_to_ami("AgentConnect", message);
2094 static struct ast_manager_event_blob *queue_agent_complete_to_ami(struct stasis_message *message)
2096 return queue_multi_channel_to_ami("AgentComplete", message);
2099 static struct ast_manager_event_blob *queue_agent_dump_to_ami(struct stasis_message *message)
2101 return queue_multi_channel_to_ami("AgentDump", message);
2104 static struct ast_manager_event_blob *queue_agent_ringnoanswer_to_ami(struct stasis_message *message)
2106 return queue_multi_channel_to_ami("AgentRingNoAnswer", message);
2109 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_called_type,
2110 .to_ami = queue_agent_called_to_ami,
2112 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_connect_type,
2113 .to_ami = queue_agent_connect_to_ami,
2115 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_complete_type,
2116 .to_ami = queue_agent_complete_to_ami,
2118 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_dump_type,
2119 .to_ami = queue_agent_dump_to_ami,
2121 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_ringnoanswer_type,
2122 .to_ami = queue_agent_ringnoanswer_to_ami,
2125 static void queue_publish_multi_channel_snapshot_blob(struct stasis_topic *topic,
2126 struct ast_channel_snapshot *caller_snapshot,
2127 struct ast_channel_snapshot *agent_snapshot,
2128 struct stasis_message_type *type, struct ast_json *blob)
2130 RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
2131 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
2137 payload = ast_multi_channel_blob_create(blob);
2142 ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
2143 if (agent_snapshot) {
2144 ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
2147 msg = stasis_message_create(type, payload);
2152 stasis_publish(topic, msg);
2155 static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent,
2156 struct stasis_message_type *type, struct ast_json *blob)
2158 RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
2159 RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
2161 ast_channel_lock(caller);
2162 caller_snapshot = ast_channel_snapshot_create(caller);
2163 ast_channel_unlock(caller);
2164 ast_channel_lock(agent);
2165 agent_snapshot = ast_channel_snapshot_create(agent);
2166 ast_channel_unlock(agent);
2168 if (!caller_snapshot || !agent_snapshot) {
2172 queue_publish_multi_channel_snapshot_blob(ast_channel_topic(caller), caller_snapshot,
2173 agent_snapshot, type, blob);
2178 * \brief Publish the member blob.
2181 * \param type Stasis message type to publish.
2182 * \param blob The information being published.
2184 * \note The json blob reference is passed to this function.
2188 static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
2190 RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
2191 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
2193 if (!blob || !type) {
2197 payload = ast_json_payload_create(blob);
2198 ast_json_unref(blob);
2203 msg = stasis_message_create(type, payload);
2208 stasis_publish(ast_manager_get_topic(), msg);
2211 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
2213 return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
2215 "MemberName", mem->membername,
2216 "Interface", mem->interface,
2217 "StateInterface", mem->state_interface,
2218 "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
2219 "Penalty", mem->penalty,
2220 "CallsTaken", mem->calls,
2221 "LastCall", (int)mem->lastcall,
2222 "LastPause", (int)mem->lastpause,
2223 "InCall", mem->in_call,
2224 "Status", mem->status,
2225 "Paused", mem->paused,
2226 "PausedReason", mem->reason_paused,
2227 "Ringinuse", mem->ringinuse);
2230 /*! \brief Check if members are available
2232 * This function checks to see if members are available to be called. If any member
2233 * is available, the function immediately returns 0. If no members are available,
2234 * then -1 is returned.
2236 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
2238 struct member *member;
2239 struct ao2_iterator mem_iter;
2242 mem_iter = ao2_iterator_init(q->members, 0);
2243 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
2244 if ((max_penalty != INT_MAX && member->penalty > max_penalty) || (min_penalty != INT_MAX && member->penalty < min_penalty)) {
2245 if (conditions & QUEUE_EMPTY_PENALTY) {
2246 ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
2251 switch (devstate ? ast_device_state(member->state_interface) : member->status) {
2252 case AST_DEVICE_INVALID:
2253 if (conditions & QUEUE_EMPTY_INVALID) {
2254 ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
2258 case AST_DEVICE_UNAVAILABLE:
2259 if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
2260 ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
2264 case AST_DEVICE_INUSE:
2265 if (conditions & QUEUE_EMPTY_INUSE) {
2266 ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
2270 case AST_DEVICE_RINGING:
2271 if (conditions & QUEUE_EMPTY_RINGING) {
2272 ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
2276 case AST_DEVICE_UNKNOWN:
2277 if (conditions & QUEUE_EMPTY_UNKNOWN) {
2278 ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
2284 if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
2285 ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
2287 } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->in_call && q->wrapuptime) {
2288 ast_debug(4, "%s is unavailable because still in call, so we can`t check "
2289 "wrapuptime (%d)\n", member->membername, q->wrapuptime);
2291 } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
2292 ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
2295 ao2_ref(member, -1);
2296 ao2_iterator_destroy(&mem_iter);
2298 ast_debug(4, "%s is available.\n", member->membername);
2304 ao2_iterator_destroy(&mem_iter);
2307 if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
2308 /* member state still may be RINGING due to lag in event message - check again with device state */
2309 return get_member_status(q, max_penalty, min_penalty, conditions, 1);
2315 * A "pool" of member objects that calls are currently pending on. If an
2316 * agent is a member of multiple queues it's possible for that agent to be
2317 * called by each of the queues at the same time. This happens because device
2318 * state is slow to notify the queue app of one of it's member's being rung.
2319 * This "pool" allows us to track which members are currently being rung while
2320 * we wait on the device state change.
2322 static struct ao2_container *pending_members;
2323 #define MAX_CALL_ATTEMPT_BUCKETS 353
2325 static int pending_members_hash(const void *obj, const int flags)
2327 const struct member *object;
2330 switch (flags & OBJ_SEARCH_MASK) {
2331 case OBJ_SEARCH_KEY:
2334 case OBJ_SEARCH_OBJECT:
2336 key = object->interface;
2342 return ast_str_case_hash(key);
2345 static int pending_members_cmp(void *obj, void *arg, int flags)
2347 const struct member *object_left = obj;
2348 const struct member *object_right = arg;
2349 const char *right_key = arg;
2352 switch (flags & OBJ_SEARCH_MASK) {
2353 case OBJ_SEARCH_OBJECT:
2354 right_key = object_right->interface;
2356 case OBJ_SEARCH_KEY:
2357 cmp = strcasecmp(object_left->interface, right_key);
2359 case OBJ_SEARCH_PARTIAL_KEY:
2360 /* Not supported by container. */
2373 static void pending_members_remove(struct member *mem)
2375 ast_debug(3, "Removed %s from pending_members\n", mem->membername);
2376 ao2_find(pending_members, mem, OBJ_POINTER | OBJ_NODATA | OBJ_UNLINK);
2379 /*! \brief set a member's status based on device state of that member's state_interface.
2381 * Lock interface list find sc, iterate through each queues queue_member list for member to
2382 * update state inside queues
2384 static void update_status(struct call_queue *q, struct member *m, const int status)
2386 if (m->status != status) {
2389 /* Remove the member from the pending members pool only when the status changes.
2390 * This is not done unconditionally because we can occasionally see multiple
2391 * device state notifications of not in use after a previous call has ended,
2392 * including after we have initiated a new call. This is more likely to
2393 * happen when there is latency in the connection to the member.
2395 pending_members_remove(m);
2398 queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
2403 * \brief Determine if a queue member is available
2404 * \retval 1 if the member is available
2405 * \retval 0 if the member is not available
2407 static int is_member_available(struct call_queue *q, struct member *mem)
2411 switch (mem->status) {
2412 case AST_DEVICE_INVALID:
2413 case AST_DEVICE_UNAVAILABLE:
2415 case AST_DEVICE_INUSE:
2416 case AST_DEVICE_BUSY:
2417 case AST_DEVICE_RINGING:
2418 case AST_DEVICE_RINGINUSE:
2419 case AST_DEVICE_ONHOLD:
2420 if (!mem->ringinuse) {
2423 /* else fall through */
2424 case AST_DEVICE_NOT_INUSE:
2425 case AST_DEVICE_UNKNOWN:
2432 /* Let wrapuptimes override device state availability */
2433 if (q->wrapuptime && mem->in_call) {
2434 available = 0; /* member is still in call, cant check wrapuptime to lastcall time */
2436 if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {
2442 /*! \brief set a member's status based on device state of that member's interface*/
2443 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
2445 struct ao2_iterator miter, qiter;
2446 struct ast_device_state_message *dev_state;
2448 struct call_queue *q;
2449 char interface[80], *slash_pos;
2450 int found = 0; /* Found this member in any queue */
2451 int found_member; /* Found this member in this queue */
2452 int avail = 0; /* Found an available member in this queue */
2454 if (ast_device_state_message_type() != stasis_message_type(msg)) {
2458 dev_state = stasis_message_data(msg);
2459 if (dev_state->eid) {
2460 /* ignore non-aggregate states */
2464 qiter = ao2_iterator_init(queues, 0);
2465 while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2470 miter = ao2_iterator_init(q->members, 0);
2471 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2472 if (!found_member) {
2473 ast_copy_string(interface, m->state_interface, sizeof(interface));
2475 if ((slash_pos = strchr(interface, '/'))) {
2476 if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2481 if (!strcasecmp(interface, dev_state->device)) {
2483 update_status(q, m, dev_state->state);
2487 /* check every member until we find one NOT_INUSE */
2489 avail = is_member_available(q, m);
2491 if (avail && found_member) {
2492 /* early exit as we've found an available member and the member of interest */
2501 ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
2503 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
2507 ao2_iterator_destroy(&miter);
2510 queue_t_unref(q, "Done with iterator");
2512 ao2_iterator_destroy(&qiter);
2515 ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
2518 ast_devstate2str(dev_state->state));
2520 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",
2523 ast_devstate2str(dev_state->state));
2529 /*! \brief Helper function which converts from extension state to device state values */
2530 static int extensionstate2devicestate(int state)
2533 case AST_EXTENSION_NOT_INUSE:
2534 state = AST_DEVICE_NOT_INUSE;
2536 case AST_EXTENSION_INUSE:
2537 state = AST_DEVICE_INUSE;
2539 case AST_EXTENSION_BUSY:
2540 state = AST_DEVICE_BUSY;
2542 case AST_EXTENSION_RINGING:
2543 state = AST_DEVICE_RINGING;
2545 case AST_EXTENSION_ONHOLD:
2546 state = AST_DEVICE_ONHOLD;
2548 case AST_EXTENSION_UNAVAILABLE:
2549 state = AST_DEVICE_UNAVAILABLE;
2551 case AST_EXTENSION_REMOVED:
2552 case AST_EXTENSION_DEACTIVATED:
2554 state = AST_DEVICE_INVALID;
2561 static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
2563 struct ao2_iterator miter, qiter;
2565 struct call_queue *q;
2566 int state = info->exten_state;
2567 int found = 0, device_state = extensionstate2devicestate(state);
2569 /* only interested in extension state updates involving device states */
2570 if (info->reason != AST_HINT_UPDATE_DEVICE) {
2574 qiter = ao2_iterator_init(queues, 0);
2575 while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2578 miter = ao2_iterator_init(q->members, 0);
2579 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2580 if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
2581 update_status(q, m, device_state);
2587 ao2_iterator_destroy(&miter);
2590 queue_t_unref(q, "Done with iterator");
2592 ao2_iterator_destroy(&qiter);
2595 ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2597 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",
2598 exten, context, device_state, ast_devstate2str(device_state));
2604 /*! \brief Return the current state of a member */
2605 static int get_queue_member_status(struct member *cur)
2607 return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
2610 /*! \brief allocate space for new queue member and set fields based on parameters passed */
2611 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
2615 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
2616 cur->ringinuse = ringinuse;
2617 cur->penalty = penalty;
2618 cur->paused = paused;
2620 time(&cur->lastpause); /* Update time of last pause */
2622 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2623 if (!ast_strlen_zero(state_interface)) {
2624 ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
2626 ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
2628 if (!ast_strlen_zero(membername)) {
2629 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2631 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2633 if (!strchr(cur->interface, '/')) {
2634 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2636 if (!strncmp(cur->state_interface, "hint:", 5)) {
2637 char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2638 char *exten = strsep(&context, "@") + 5;
2640 ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2641 ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2643 cur->status = get_queue_member_status(cur);
2650 static int compress_char(const char c)
2654 } else if (c > 96) {
2660 static int member_hash_fn(const void *obj, const int flags)
2662 const struct member *mem = obj;
2663 const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
2664 const char *chname = strchr(interface, '/');
2670 for (i = 0; i < 5 && chname[i]; i++) {
2671 ret += compress_char(chname[i]) << (i * 6);
2676 static int member_cmp_fn(void *obj1, void *obj2, int flags)
2678 struct member *mem1 = obj1;
2679 struct member *mem2 = obj2;
2680 const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
2682 return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
2686 * \brief Initialize Queue default values.
2687 * \note the queue's lock must be held before executing this function
2689 static void init_queue(struct call_queue *q)
2692 struct penalty_rule *pr_iter;
2695 q->retry = DEFAULT_RETRY;
2696 q->timeout = DEFAULT_TIMEOUT;
2699 ast_string_field_set(q, context, "");
2701 q->announcefrequency = 0;
2702 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
2703 q->announceholdtime = 1;
2704 q->announcepositionlimit = 10; /* Default 10 positions */
2705 q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
2706 q->roundingseconds = 0; /* Default - don't announce seconds */
2707 q->servicelevel = 0;
2709 q->announce_to_first_user = 0;
2710 q->setinterfacevar = 0;
2712 q->setqueueentryvar = 0;
2713 q->autofill = autofill_default;
2714 q->montype = montype_default;
2715 q->monfmt[0] = '\0';
2716 q->reportholdtime = 0;
2718 q->penaltymemberslimit = 0;
2720 q->leavewhenempty = 0;
2723 q->timeoutrestart = 0;
2724 q->periodicannouncefrequency = 0;
2725 q->randomperiodicannounce = 0;
2726 q->numperiodicannounce = 0;
2727 q->autopause = QUEUE_AUTOPAUSE_OFF;
2728 q->timeoutpriority = TIMEOUT_PRIORITY_APP;
2729 q->autopausedelay = 0;
2731 if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
2732 /* linear strategy depends on order, so we have to place all members in a single bucket */
2733 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
2735 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
2740 ast_string_field_set(q, sound_next, "queue-youarenext");
2741 ast_string_field_set(q, sound_thereare, "queue-thereare");
2742 ast_string_field_set(q, sound_calls, "queue-callswaiting");
2743 ast_string_field_set(q, queue_quantity1, "queue-quantity1");
2744 ast_string_field_set(q, queue_quantity2, "queue-quantity2");
2745 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
2746 ast_string_field_set(q, sound_minutes, "queue-minutes");
2747 ast_string_field_set(q, sound_minute, "queue-minute");
2748 ast_string_field_set(q, sound_seconds, "queue-seconds");
2749 ast_string_field_set(q, sound_thanks, "queue-thankyou");
2750 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
2752 if (!q->sound_periodicannounce[0]) {
2753 q->sound_periodicannounce[0] = ast_str_create(32);
2756 if (q->sound_periodicannounce[0]) {
2757 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
2760 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
2761 if (q->sound_periodicannounce[i]) {
2762 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
2766 while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
2770 /* On restart assume no members are available.
2771 * The queue_avail hint is a boolean state to indicate whether a member is available or not.
2773 * This seems counter intuitive, but is required to light a BLF
2774 * AST_DEVICE_INUSE indicates no members are available.
2775 * AST_DEVICE_NOT_INUSE indicates a member is available.
2777 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
2780 static void clear_queue(struct call_queue *q)
2783 q->callscompleted = 0;
2784 q->callsabandoned = 0;
2785 q->callscompletedinsl = 0;
2786 q->callsabandonedinsl = 0;
2791 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
2792 while ((mem = ao2_iterator_next(&mem_iter))) {
2798 ao2_iterator_destroy(&mem_iter);
2803 * \brief Change queue penalty by adding rule.
2805 * Check rule for errors with time or fomatting, see if rule is relative to rest
2806 * of queue, iterate list of rules to find correct insertion point, insert and return.
2807 * \retval -1 on failure
2808 * \retval 0 on success
2809 * \note Call this with the rule_lists locked
2811 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
2813 char *timestr, *maxstr, *minstr, *contentdup;
2814 struct penalty_rule *rule = NULL, *rule_iter;
2815 struct rule_list *rl_iter;
2816 int penaltychangetime, inserted = 0;
2818 if (!(rule = ast_calloc(1, sizeof(*rule)))) {
2822 contentdup = ast_strdupa(content);
2824 if (!(maxstr = strchr(contentdup, ','))) {
2825 ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
2831 timestr = contentdup;
2833 if ((penaltychangetime = atoi(timestr)) < 0) {
2834 ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);