2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, 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 * \arg Config in \ref Config_qu queues.conf
27 * \par Development notes
28 * \note 2004-11-25: Persistent Dynamic Members added by:
29 * NetNation Communications (www.netnation.com)
30 * Kevin Lindsay <kevinl@netnation.com>
32 * Each dynamic agent in each queue is now stored in the astdb.
33 * When asterisk is restarted, each agent will be automatically
34 * readded into their recorded queues. This feature can be
35 * configured with the 'persistent_members=<1|0>' setting in the
36 * '[general]' category in queues.conf. The default is on.
38 * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
40 * \note These features added by David C. Troy <dave@toad.net>:
41 * - Per-queue holdtime calculation
42 * - Estimated holdtime announcement
43 * - Position announcement
44 * - Abandoned/completed call counters
45 * - Failout timer passed as optional app parameter
46 * - Optional monitoring of calls, started when call is answered
48 * Patch Version 1.07 2003-12-24 01
50 * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
51 * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
53 * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
54 * by Matthew Enger <m.enger@xi.com.au>
56 * \ingroup applications
60 <depend>res_monitor</depend>
65 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
68 #include <sys/signal.h>
69 #include <netinet/in.h>
72 #include "asterisk/lock.h"
73 #include "asterisk/file.h"
74 #include "asterisk/channel.h"
75 #include "asterisk/pbx.h"
76 #include "asterisk/app.h"
77 #include "asterisk/linkedlists.h"
78 #include "asterisk/module.h"
79 #include "asterisk/translate.h"
80 #include "asterisk/say.h"
81 #include "asterisk/features.h"
82 #include "asterisk/musiconhold.h"
83 #include "asterisk/cli.h"
84 #include "asterisk/manager.h"
85 #include "asterisk/config.h"
86 #include "asterisk/monitor.h"
87 #include "asterisk/utils.h"
88 #include "asterisk/causes.h"
89 #include "asterisk/astdb.h"
90 #include "asterisk/devicestate.h"
91 #include "asterisk/stringfields.h"
92 #include "asterisk/event.h"
93 #include "asterisk/astobj2.h"
94 #include "asterisk/strings.h"
95 #include "asterisk/global_datastores.h"
96 #include "asterisk/taskprocessor.h"
97 #include "asterisk/aoc.h"
98 #include "asterisk/callerid.h"
99 #include "asterisk/cel.h"
100 #include "asterisk/data.h"
102 /* Define, to debug reference counts on queues, without debugging reference counts on queue members */
103 /* #define REF_DEBUG_ONLY_QUEUES */
106 * \par Please read before modifying this file.
107 * There are three locks which are regularly used
108 * throughout this file, the queue list lock, the lock
109 * for each individual queue, and the interface list lock.
110 * Please be extra careful to always lock in the following order
112 * 2) individual queue lock
113 * 3) interface list lock
114 * This order has sort of "evolved" over the lifetime of this
115 * application, but it is now in place this way, so please adhere
120 <application name="Queue" language="en_US">
122 Queue a call for a call queue.
125 <parameter name="queuename" required="true" />
126 <parameter name="options">
129 <para>Mark all calls as "answered elsewhere" when cancelled.</para>
132 <para>Continue in the dialplan if the callee hangs up.</para>
135 <para>data-quality (modem) call (minimum delay).</para>
138 <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
141 <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
144 <para>No retries on the timeout; will exit this application and
145 go to the next step.</para>
148 <para>Ignore call forward requests from queue members and do nothing
149 when they are requested.</para>
152 <para>Asterisk will ignore any connected line update requests or any redirecting party
153 update requests it may receive on this dial attempt.</para>
156 <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
159 <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
162 <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
165 <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
168 <para>Allow the <emphasis>called</emphasis> user to write the conversation to
169 disk via Monitor.</para>
172 <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
173 disk via Monitor.</para>
176 <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
177 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
180 <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
181 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
184 <para>Allow the <emphasis>called</emphasis> user to write the conversation
185 to disk via MixMonitor.</para>
188 <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
189 disk via MixMonitor.</para>
193 <parameter name="URL">
194 <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
196 <parameter name="announceoverride" />
197 <parameter name="timeout">
198 <para>Will cause the queue to fail out after a specified number of
199 seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
200 <replaceable>retry</replaceable> cycle.</para>
202 <parameter name="AGI">
203 <para>Will setup an AGI script to be executed on the calling party's channel once they are
204 connected to a queue member.</para>
206 <parameter name="macro">
207 <para>Will run a macro on the calling party's channel once they are connected to a queue member.</para>
209 <parameter name="gosub">
210 <para>Will run a gosub on the calling party's channel once they are connected to a queue member.</para>
212 <parameter name="rule">
213 <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
215 <parameter name="position">
216 <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
217 would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
218 the caller third in the queue.</para>
222 <para>In addition to transferring the call, a call may be parked and then picked
223 up by another user.</para>
224 <para>This application will return to the dialplan if the queue does not exist, or
225 any of the join options cause the caller to not enter the queue.</para>
226 <para>This application sets the following channel variable upon completion:</para>
228 <variable name="QUEUESTATUS">
229 <para>The status of the call as a text string.</para>
230 <value name="TIMEOUT" />
231 <value name="FULL" />
232 <value name="JOINEMPTY" />
233 <value name="LEAVEEMPTY" />
234 <value name="JOINUNAVAIL" />
235 <value name="LEAVEUNAVAIL" />
236 <value name="CONTINUE" />
241 <ref type="application">AddQueueMember</ref>
242 <ref type="application">RemoveQueueMember</ref>
243 <ref type="application">PauseQueueMember</ref>
244 <ref type="application">UnpauseQueueMember</ref>
245 <ref type="application">AgentLogin</ref>
246 <ref type="function">QUEUE_MEMBER_COUNT</ref>
247 <ref type="function">QUEUE_MEMBER_LIST</ref>
248 <ref type="function">QUEUE_WAITING_COUNT</ref>
251 <application name="AddQueueMember" language="en_US">
253 Dynamically adds queue members.
256 <parameter name="queuename" required="true" />
257 <parameter name="interface" />
258 <parameter name="penalty" />
259 <parameter name="options" />
260 <parameter name="membername" />
261 <parameter name="stateinterface" />
264 <para>Dynamically adds interface to an existing queue. If the interface is
265 already in the queue it will return an error.</para>
266 <para>This application sets the following channel variable upon completion:</para>
268 <variable name="AQMSTATUS">
269 <para>The status of the attempt to add a queue member as a text string.</para>
270 <value name="ADDED" />
271 <value name="MEMBERALREADY" />
272 <value name="NOSUCHQUEUE" />
277 <ref type="application">RemoveQueueMember</ref>
278 <ref type="application">PauseQueueMember</ref>
279 <ref type="application">UnpauseQueueMember</ref>
280 <ref type="application">AgentLogin</ref>
283 <application name="RemoveQueueMember" language="en_US">
285 Dynamically removes queue members.
288 <parameter name="queuename" required="true" />
289 <parameter name="interface" />
290 <parameter name="options" />
293 <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
294 <para>This application sets the following channel variable upon completion:</para>
296 <variable name="RQMSTATUS">
297 <value name="REMOVED" />
298 <value name="NOTINQUEUE" />
299 <value name="NOSUCHQUEUE" />
302 <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
305 <ref type="application">Queue</ref>
306 <ref type="application">AddQueueMember</ref>
307 <ref type="application">PauseQueueMember</ref>
308 <ref type="application">UnpauseQueueMember</ref>
311 <application name="PauseQueueMember" language="en_US">
313 Pauses a queue member.
316 <parameter name="queuename" />
317 <parameter name="interface" required="true" />
318 <parameter name="options" />
319 <parameter name="reason">
320 <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
324 <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
325 This prevents any calls from being sent from the queue to the interface until it is
326 unpaused with UnpauseQueueMember or the manager interface. If no queuename is given,
327 the interface is paused in every queue it is a member of. The application will fail if the
328 interface is not found.</para>
329 <para>This application sets the following channel variable upon completion:</para>
331 <variable name="PQMSTATUS">
332 <para>The status of the attempt to pause a queue member as a text string.</para>
333 <value name="PAUSED" />
334 <value name="NOTFOUND" />
337 <para>Example: PauseQueueMember(,SIP/3000)</para>
340 <ref type="application">UnpauseQueueMember</ref>
343 <application name="UnpauseQueueMember" language="en_US">
345 Unpauses a queue member.
348 <parameter name="queuename" />
349 <parameter name="interface" required="true" />
350 <parameter name="options" />
351 <parameter name="reason">
352 <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
356 <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
357 and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
358 <para>This application sets the following channel variable upon completion:</para>
360 <variable name="UPQMSTATUS">
361 <para>The status of the attempt to unpause a queue member as a text string.</para>
362 <value name="UNPAUSED" />
363 <value name="NOTFOUND" />
366 <para>Example: UnpauseQueueMember(,SIP/3000)</para>
369 <ref type="application">PauseQueueMember</ref>
372 <application name="QueueLog" language="en_US">
374 Writes to the queue_log file.
377 <parameter name="queuename" required="true" />
378 <parameter name="uniqueid" required="true" />
379 <parameter name="agent" required="true" />
380 <parameter name="event" required="true" />
381 <parameter name="additionalinfo" />
384 <para>Allows you to write your own events into the queue log.</para>
385 <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
388 <ref type="application">Queue</ref>
391 <function name="QUEUE_VARIABLES" language="en_US">
393 Return Queue information in variables.
396 <parameter name="queuename" required="true">
398 <enum name="QUEUEMAX">
399 <para>Maxmimum number of calls allowed.</para>
401 <enum name="QUEUESTRATEGY">
402 <para>The strategy of the queue.</para>
404 <enum name="QUEUECALLS">
405 <para>Number of calls currently in the queue.</para>
407 <enum name="QUEUEHOLDTIME">
408 <para>Current average hold time.</para>
410 <enum name="QUEUECOMPLETED">
411 <para>Number of completed calls for the queue.</para>
413 <enum name="QUEUEABANDONED">
414 <para>Number of abandoned calls.</para>
416 <enum name="QUEUESRVLEVEL">
417 <para>Queue service level.</para>
419 <enum name="QUEUESRVLEVELPERF">
420 <para>Current service level performance.</para>
426 <para>Makes the following queue variables available.</para>
427 <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
430 <function name="QUEUE_MEMBER" language="en_US">
432 Count number of members answering a queue.
435 <parameter name="queuename" required="true" />
436 <parameter name="option" required="true">
439 <para>Returns the number of logged-in members for the specified queue.</para>
442 <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>
445 <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
448 <para>Returns the total number of members for the specified queue.</para>
454 <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
457 <function name="QUEUE_MEMBER_COUNT" language="en_US">
459 Count number of members answering a queue.
462 <parameter name="queuename" required="true" />
465 <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
466 <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
469 <ref type="function">QUEUE_MEMBER_LIST</ref>
472 <function name="QUEUE_WAITING_COUNT" language="en_US">
474 Count number of calls currently waiting in a queue.
477 <parameter name="queuename" />
480 <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
483 <function name="QUEUE_MEMBER_LIST" language="en_US">
485 Returns a list of interfaces on a queue.
488 <parameter name="queuename" required="true" />
491 <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
494 <ref type="function">QUEUE_MEMBER_COUNT</ref>
497 <function name="QUEUE_MEMBER_PENALTY" language="en_US">
499 Gets or sets queue members penalty.
502 <parameter name="queuename" required="true" />
503 <parameter name="interface" required="true" />
506 <para>Gets or sets queue members penalty.</para>
509 <manager name="Queues" language="en_US">
514 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
519 <manager name="QueueStatus" language="en_US">
524 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
525 <parameter name="Queue" />
526 <parameter name="Member" />
531 <manager name="QueueSummary" language="en_US">
536 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
537 <parameter name="Queue" />
542 <manager name="QueueAdd" language="en_US">
544 Add interface to queue.
547 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
548 <parameter name="Queue" required="true" />
549 <parameter name="Interface" required="true" />
550 <parameter name="Penalty" />
551 <parameter name="Paused" />
552 <parameter name="MemberName" />
553 <parameter name="StateInterface" />
558 <manager name="QueueRemove" language="en_US">
560 Remove interface from queue.
563 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
564 <parameter name="Queue" required="true" />
565 <parameter name="Interface" required="true" />
570 <manager name="QueuePause" language="en_US">
572 Makes a queue member temporarily unavailable.
575 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
576 <parameter name="Interface" required="true" />
577 <parameter name="Paused" required="true" />
578 <parameter name="Queue" />
579 <parameter name="Reason" />
584 <manager name="QueueLog" language="en_US">
586 Adds custom entry in queue_log.
589 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
590 <parameter name="Queue" required="true" />
591 <parameter name="Event" required="true" />
592 <parameter name="Uniqueid" />
593 <parameter name="Interface" />
594 <parameter name="Message" />
599 <manager name="QueuePenalty" language="en_US">
601 Set the penalty for a queue member.
604 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
605 <parameter name="Interface" required="true" />
606 <parameter name="Penalty" required="true" />
607 <parameter name="Queue" />
612 <manager name="QueueRule" language="en_US">
617 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
618 <parameter name="Rule" />
623 <manager name="QueueReload" language="en_US">
625 Reload a queue, queues, or any sub-section of a queue or queues.
628 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
629 <parameter name="Queue" />
630 <parameter name="Members">
636 <parameter name="Rules">
642 <parameter name="Parameters">
652 <manager name="QueueReset" language="en_US">
654 Reset queue statistics.
657 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
658 <parameter name="Queue" />
666 QUEUE_STRATEGY_RINGALL = 0,
667 QUEUE_STRATEGY_LEASTRECENT,
668 QUEUE_STRATEGY_FEWESTCALLS,
669 QUEUE_STRATEGY_RANDOM,
670 QUEUE_STRATEGY_RRMEMORY,
671 QUEUE_STRATEGY_LINEAR,
672 QUEUE_STRATEGY_WRANDOM
676 QUEUE_AUTOPAUSE_OFF = 0,
681 enum queue_reload_mask {
682 QUEUE_RELOAD_PARAMETERS = (1 << 0),
683 QUEUE_RELOAD_MEMBER = (1 << 1),
684 QUEUE_RELOAD_RULES = (1 << 2),
685 QUEUE_RESET_STATS = (1 << 3),
688 static const struct strategy {
692 { QUEUE_STRATEGY_RINGALL, "ringall" },
693 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
694 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
695 { QUEUE_STRATEGY_RANDOM, "random" },
696 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
697 { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
698 { QUEUE_STRATEGY_LINEAR, "linear" },
699 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
702 static const struct autopause {
705 } autopausesmodes [] = {
706 { QUEUE_AUTOPAUSE_OFF,"no" },
707 { QUEUE_AUTOPAUSE_ON, "yes" },
708 { QUEUE_AUTOPAUSE_ALL,"all" },
712 static struct ast_taskprocessor *devicestate_tps;
714 #define DEFAULT_RETRY 5
715 #define DEFAULT_TIMEOUT 15
716 #define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
717 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
718 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /*!< The minimum number of seconds between position announcements \
719 The default value of 15 provides backwards compatibility */
720 #define MAX_QUEUE_BUCKETS 53
722 #define RES_OKAY 0 /*!< Action completed */
723 #define RES_EXISTS (-1) /*!< Entry already exists */
724 #define RES_OUTOFMEMORY (-2) /*!< Out of memory */
725 #define RES_NOSUCHQUEUE (-3) /*!< No such queue */
726 #define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
728 static char *app = "Queue";
730 static char *app_aqm = "AddQueueMember" ;
732 static char *app_rqm = "RemoveQueueMember" ;
734 static char *app_pqm = "PauseQueueMember" ;
736 static char *app_upqm = "UnpauseQueueMember" ;
738 static char *app_ql = "QueueLog" ;
740 /*! \brief Persistent Members astdb family */
741 static const char * const pm_family = "Queue/PersistentMembers";
742 /* The maximum length of each persistent member queue database entry */
743 #define PM_MAX_LEN 8192
745 /*! \brief queues.conf [general] option */
746 static int queue_persistent_members = 0;
748 /*! \brief queues.conf per-queue weight option */
749 static int use_weight = 0;
751 /*! \brief queues.conf [general] option */
752 static int autofill_default = 0;
754 /*! \brief queues.conf [general] option */
755 static int montype_default = 0;
757 /*! \brief queues.conf [general] option */
758 static int shared_lastcall = 0;
760 /*! \brief Subscription to device state change events */
761 static struct ast_event_sub *device_state_sub;
763 /*! \brief queues.conf [general] option */
764 static int update_cdr = 0;
770 QUEUE_LEAVEEMPTY = 3,
771 QUEUE_JOINUNAVAIL = 4,
772 QUEUE_LEAVEUNAVAIL = 5,
777 static const struct {
778 enum queue_result id;
780 } queue_results[] = {
781 { QUEUE_UNKNOWN, "UNKNOWN" },
782 { QUEUE_TIMEOUT, "TIMEOUT" },
783 { QUEUE_JOINEMPTY,"JOINEMPTY" },
784 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
785 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
786 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
787 { QUEUE_FULL, "FULL" },
788 { QUEUE_CONTINUE, "CONTINUE" },
791 enum queue_timeout_priority {
792 TIMEOUT_PRIORITY_APP,
793 TIMEOUT_PRIORITY_CONF,
796 /*! \brief We define a custom "local user" structure because we
797 * use it not only for keeping track of what is in use but
798 * also for keeping track of who we're dialing.
800 * There are two "links" defined in this structure, q_next and call_next.
801 * q_next links ALL defined callattempt structures into a linked list. call_next is
802 * a link which allows for a subset of the callattempts to be traversed. This subset
803 * is used in wait_for_answer so that irrelevant callattempts are not traversed. This
804 * also is helpful so that queue logs are always accurate in the case where a call to
805 * a member times out, especially if using the ringall strategy.
809 struct callattempt *q_next;
810 struct callattempt *call_next;
811 struct ast_channel *chan;
816 struct call_queue *lastqueue;
817 struct member *member;
818 /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
819 struct ast_party_connected_line connected;
820 /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
821 unsigned int pending_connected_update:1;
822 /*! TRUE if caller id is not available for connected line */
823 unsigned int dial_callerid_absent:1;
824 struct ast_aoc_decoded *aoc_s_rate_list;
829 struct call_queue *parent; /*!< What queue is our parent */
830 char moh[80]; /*!< Name of musiconhold to be used */
831 char announce[80]; /*!< Announcement to play for member when call is answered */
832 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
833 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
834 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
835 int pos; /*!< Where we are in the queue */
836 int prio; /*!< Our priority */
837 int last_pos_said; /*!< Last position we told the user */
838 int ring_when_ringing; /*!< Should we only use ring indication when a channel is ringing? */
839 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
840 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
841 time_t last_pos; /*!< Last time we told the user their position */
842 int opos; /*!< Where we started in the queue */
843 int handled; /*!< Whether our call was handled */
844 int pending; /*!< Non-zero if we are attempting to call a member */
845 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
846 int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
847 int linpos; /*!< If using linear strategy, what position are we at? */
848 int linwrapped; /*!< Is the linpos wrapped? */
849 time_t start; /*!< When we started holding */
850 time_t expire; /*!< When this entry should expire (time out of queue) */
851 int cancel_answered_elsewhere; /*!< Whether we should force the CAE flag on this call (C) option*/
852 struct ast_channel *chan; /*!< Our channel */
853 AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
854 struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
855 struct queue_ent *next; /*!< The next queue entry */
859 char interface[80]; /*!< Technology/Location to dial to reach this member*/
860 char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
861 char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
862 char state_interface[80]; /*!< Technology/Location from which to read devicestate changes */
863 char membername[80]; /*!< Member name to use in queue logs */
864 int penalty; /*!< Are we a last resort? */
865 int calls; /*!< Number of calls serviced by this member */
866 int dynamic; /*!< Are we dynamically added? */
867 int realtime; /*!< Is this member realtime? */
868 int status; /*!< Status of queue member */
869 int paused; /*!< Are we paused (not accepting calls)? */
870 time_t lastcall; /*!< When last successful call was hungup */
871 struct call_queue *lastqueue; /*!< Last queue we received a call */
872 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
873 unsigned int delme:1; /*!< Flag to delete entry on reload */
874 char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
877 enum empty_conditions {
878 QUEUE_EMPTY_PENALTY = (1 << 0),
879 QUEUE_EMPTY_PAUSED = (1 << 1),
880 QUEUE_EMPTY_INUSE = (1 << 2),
881 QUEUE_EMPTY_RINGING = (1 << 3),
882 QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
883 QUEUE_EMPTY_INVALID = (1 << 5),
884 QUEUE_EMPTY_UNKNOWN = (1 << 6),
885 QUEUE_EMPTY_WRAPUP = (1 << 7),
888 /* values used in multi-bit flags in call_queue */
889 #define ANNOUNCEHOLDTIME_ALWAYS 1
890 #define ANNOUNCEHOLDTIME_ONCE 2
891 #define QUEUE_EVENT_VARIABLES 3
893 struct penalty_rule {
894 int time; /*!< Number of seconds that need to pass before applying this rule */
895 int max_value; /*!< The amount specified in the penalty rule for max penalty */
896 int min_value; /*!< The amount specified in the penalty rule for min penalty */
897 int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
898 int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
899 AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
902 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
903 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
904 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
905 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
908 AST_DECLARE_STRING_FIELDS(
910 AST_STRING_FIELD(name);
911 /*! Music on Hold class */
912 AST_STRING_FIELD(moh);
913 /*! Announcement to play when call is answered */
914 AST_STRING_FIELD(announce);
916 AST_STRING_FIELD(context);
917 /*! Macro to run upon member connection */
918 AST_STRING_FIELD(membermacro);
919 /*! Gosub to run upon member connection */
920 AST_STRING_FIELD(membergosub);
921 /*! Default rule to use if none specified in call to Queue() */
922 AST_STRING_FIELD(defaultrule);
923 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
924 AST_STRING_FIELD(sound_next);
925 /*! Sound file: "There are currently" (def. queue-thereare) */
926 AST_STRING_FIELD(sound_thereare);
927 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
928 AST_STRING_FIELD(sound_calls);
929 /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
930 AST_STRING_FIELD(queue_quantity1);
931 /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
932 AST_STRING_FIELD(queue_quantity2);
933 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
934 AST_STRING_FIELD(sound_holdtime);
935 /*! Sound file: "minutes." (def. queue-minutes) */
936 AST_STRING_FIELD(sound_minutes);
937 /*! Sound file: "minute." (def. queue-minute) */
938 AST_STRING_FIELD(sound_minute);
939 /*! Sound file: "seconds." (def. queue-seconds) */
940 AST_STRING_FIELD(sound_seconds);
941 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
942 AST_STRING_FIELD(sound_thanks);
943 /*! Sound file: Custom announce for caller, no default */
944 AST_STRING_FIELD(sound_callerannounce);
945 /*! Sound file: "Hold time" (def. queue-reporthold) */
946 AST_STRING_FIELD(sound_reporthold);
948 /*! Sound files: Custom announce, no default */
949 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
951 unsigned int eventwhencalled:2;
952 unsigned int ringinuse:1;
953 unsigned int setinterfacevar:1;
954 unsigned int setqueuevar:1;
955 unsigned int setqueueentryvar:1;
956 unsigned int reportholdtime:1;
957 unsigned int wrapped:1;
958 unsigned int timeoutrestart:1;
959 unsigned int announceholdtime:2;
960 unsigned int announceposition:3;
962 unsigned int maskmemberstatus:1;
963 unsigned int realtime:1;
964 unsigned int found:1;
965 unsigned int relativeperiodicannounce:1;
966 enum empty_conditions joinempty;
967 enum empty_conditions leavewhenempty;
968 int announcepositionlimit; /*!< How many positions we announce? */
969 int announcefrequency; /*!< How often to announce their position */
970 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
971 int periodicannouncefrequency; /*!< How often to play periodic announcement */
972 int numperiodicannounce; /*!< The number of periodic announcements configured */
973 int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
974 int roundingseconds; /*!< How many seconds do we round to? */
975 int holdtime; /*!< Current avg holdtime, based on an exponential average */
976 int talktime; /*!< Current avg talktime, based on the same exponential average */
977 int callscompleted; /*!< Number of queue calls completed */
978 int callsabandoned; /*!< Number of queue calls abandoned */
979 int servicelevel; /*!< seconds setting for servicelevel*/
980 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
981 char monfmt[8]; /*!< Format to use when recording calls */
982 int montype; /*!< Monitor type Monitor vs. MixMonitor */
983 int count; /*!< How many entries */
984 int maxlen; /*!< Max number of entries */
985 int wrapuptime; /*!< Wrapup Time */
986 int penaltymemberslimit; /*!< Disregard penalty when queue has fewer than this many members */
988 int retry; /*!< Retry calling everyone after this amount of time */
989 int timeout; /*!< How long to wait for an answer */
990 int weight; /*!< Respective weight */
991 int autopause; /*!< Auto pause queue members if they fail to answer */
992 int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
994 /* Queue strategy things */
995 int rrpos; /*!< Round Robin - position */
996 int memberdelay; /*!< Seconds to delay connecting member to caller */
997 int autofill; /*!< Ignore the head call status and ring an available agent */
999 struct ao2_container *members; /*!< Head of the list of members */
1001 * \brief Number of members _logged in_
1002 * \note There will be members in the members container that are not logged
1003 * in, so this can not simply be replaced with ao2_container_count().
1006 struct queue_ent *head; /*!< Head of the list of callers */
1007 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
1008 AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
1013 AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
1014 AST_LIST_ENTRY(rule_list) list;
1017 static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
1019 static struct ao2_container *queues;
1021 static void update_realtime_members(struct call_queue *q);
1022 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
1024 static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
1025 /*! \brief sets the QUEUESTATUS channel variable */
1026 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
1030 for (i = 0; i < ARRAY_LEN(queue_results); i++) {
1031 if (queue_results[i].id == res) {
1032 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
1038 static const char *int2strat(int strategy)
1042 for (x = 0; x < ARRAY_LEN(strategies); x++) {
1043 if (strategy == strategies[x].strategy)
1044 return strategies[x].name;
1050 static int strat2int(const char *strategy)
1054 for (x = 0; x < ARRAY_LEN(strategies); x++) {
1055 if (!strcasecmp(strategy, strategies[x].name))
1056 return strategies[x].strategy;
1062 static int autopause2int(const char *autopause)
1065 /*This 'double check' that default value is OFF */
1066 if (ast_strlen_zero(autopause))
1067 return QUEUE_AUTOPAUSE_OFF;
1069 /*This 'double check' is to ensure old values works */
1070 if(ast_true(autopause))
1071 return QUEUE_AUTOPAUSE_ON;
1073 for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1074 if (!strcasecmp(autopause, autopausesmodes[x].name))
1075 return autopausesmodes[x].autopause;
1078 /*This 'double check' that default value is OFF */
1079 return QUEUE_AUTOPAUSE_OFF;
1082 static int queue_hash_cb(const void *obj, const int flags)
1084 const struct call_queue *q = obj;
1086 return ast_str_case_hash(q->name);
1089 static int queue_cmp_cb(void *obj, void *arg, int flags)
1091 struct call_queue *q = obj, *q2 = arg;
1092 return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1095 #ifdef REF_DEBUG_ONLY_QUEUES
1096 #define queue_ref(a) __ao2_ref_debug(a,1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__)
1097 #define queue_unref(a) __ao2_ref_debug(a,-1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__)
1098 #define queue_t_ref(a,b) __ao2_ref_debug(a,1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1099 #define queue_t_unref(a,b) __ao2_ref_debug(a,-1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1100 #define queues_t_link(c,q,tag) __ao2_link_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1101 #define queues_t_unlink(c,q,tag) __ao2_unlink_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1103 #define queue_t_ref(a,b) queue_ref(a)
1104 #define queue_t_unref(a,b) queue_unref(a)
1105 #define queues_t_link(c,q,tag) ao2_t_link(c,q,tag)
1106 #define queues_t_unlink(c,q,tag) ao2_t_unlink(c,q,tag)
1107 static inline struct call_queue *queue_ref(struct call_queue *q)
1113 static inline struct call_queue *queue_unref(struct call_queue *q)
1120 /*! \brief Set variables of queue */
1121 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
1123 char interfacevar[256]="";
1126 if (q->setqueuevar) {
1128 if (q->callscompleted > 0)
1129 sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
1131 snprintf(interfacevar, sizeof(interfacevar),
1132 "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1133 q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
1135 pbx_builtin_setvar_multiple(chan, interfacevar);
1139 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
1140 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
1142 struct queue_ent *cur;
1155 /* every queue_ent must have a reference to it's parent call_queue, this
1156 * reference does not go away until the end of the queue_ent's life, meaning
1157 * that even when the queue_ent leaves the call_queue this ref must remain. */
1160 new->pos = ++(*pos);
1164 /*! \brief Check if members are available
1166 * This function checks to see if members are available to be called. If any member
1167 * is available, the function immediately returns 0. If no members are available,
1168 * then -1 is returned.
1170 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions)
1172 struct member *member;
1173 struct ao2_iterator mem_iter;
1176 mem_iter = ao2_iterator_init(q->members, 0);
1177 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
1178 if ((max_penalty && (member->penalty > max_penalty)) || (min_penalty && (member->penalty < min_penalty))) {
1179 if (conditions & QUEUE_EMPTY_PENALTY) {
1180 ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
1185 switch (member->status) {
1186 case AST_DEVICE_INVALID:
1187 if (conditions & QUEUE_EMPTY_INVALID) {
1188 ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
1191 case AST_DEVICE_UNAVAILABLE:
1192 if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
1193 ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
1196 case AST_DEVICE_INUSE:
1197 if (conditions & QUEUE_EMPTY_INUSE) {
1198 ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
1201 case AST_DEVICE_UNKNOWN:
1202 if (conditions & QUEUE_EMPTY_UNKNOWN) {
1203 ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
1207 if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
1208 ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
1210 } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
1211 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);
1215 ao2_ref(member, -1);
1216 ao2_iterator_destroy(&mem_iter);
1217 ast_debug(4, "%s is available.\n", member->membername);
1223 ao2_iterator_destroy(&mem_iter);
1229 struct statechange {
1230 AST_LIST_ENTRY(statechange) entry;
1235 /*! \brief set a member's status based on device state of that member's state_interface.
1237 * Lock interface list find sc, iterate through each queues queue_member list for member to
1238 * update state inside queues
1240 static int update_status(struct call_queue *q, struct member *m, const int status)
1244 if (q->maskmemberstatus)
1247 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1250 "MemberName: %s\r\n"
1251 "Membership: %s\r\n"
1253 "CallsTaken: %d\r\n"
1257 q->name, m->interface, m->membername, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
1258 m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
1264 /*! \brief set a member's status based on device state of that member's interface*/
1265 static int handle_statechange(void *datap)
1267 struct statechange *sc = datap;
1268 struct ao2_iterator miter, qiter;
1270 struct call_queue *q;
1271 char interface[80], *slash_pos;
1274 qiter = ao2_iterator_init(queues, 0);
1275 while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
1278 miter = ao2_iterator_init(q->members, 0);
1279 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
1280 ast_copy_string(interface, m->state_interface, sizeof(interface));
1282 if ((slash_pos = strchr(interface, '/')))
1283 if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/')))
1286 if (!strcasecmp(interface, sc->dev)) {
1288 update_status(q, m, sc->state);
1293 ao2_iterator_destroy(&miter);
1296 queue_t_unref(q, "Done with iterator");
1298 ao2_iterator_destroy(&qiter);
1301 ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1303 ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1309 static void device_state_cb(const struct ast_event *event, void *unused)
1311 enum ast_device_state state;
1313 struct statechange *sc;
1316 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
1317 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
1319 if (ast_strlen_zero(device)) {
1320 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
1323 datapsize = sizeof(*sc) + strlen(device) + 1;
1324 if (!(sc = ast_calloc(1, datapsize))) {
1325 ast_log(LOG_ERROR, "failed to calloc a state change struct\n");
1329 strcpy(sc->dev, device);
1330 if (ast_taskprocessor_push(devicestate_tps, handle_statechange, sc) < 0) {
1335 /*! \brief Helper function which converts from extension state to device state values */
1336 static int extensionstate2devicestate(int state)
1339 case AST_EXTENSION_NOT_INUSE:
1340 state = AST_DEVICE_NOT_INUSE;
1342 case AST_EXTENSION_INUSE:
1343 state = AST_DEVICE_INUSE;
1345 case AST_EXTENSION_BUSY:
1346 state = AST_DEVICE_BUSY;
1348 case AST_EXTENSION_RINGING:
1349 state = AST_DEVICE_RINGING;
1351 case AST_EXTENSION_ONHOLD:
1352 state = AST_DEVICE_ONHOLD;
1354 case AST_EXTENSION_UNAVAILABLE:
1355 state = AST_DEVICE_UNAVAILABLE;
1357 case AST_EXTENSION_REMOVED:
1358 case AST_EXTENSION_DEACTIVATED:
1360 state = AST_DEVICE_INVALID;
1367 static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data)
1369 struct ao2_iterator miter, qiter;
1371 struct call_queue *q;
1372 int found = 0, device_state = extensionstate2devicestate(state);
1374 qiter = ao2_iterator_init(queues, 0);
1375 while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
1378 miter = ao2_iterator_init(q->members, 0);
1379 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
1380 if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
1381 update_status(q, m, device_state);
1387 ao2_iterator_destroy(&miter);
1390 queue_t_unref(q, "Done with iterator");
1392 ao2_iterator_destroy(&qiter);
1395 ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
1397 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",
1398 exten, context, device_state, ast_devstate2str(device_state));
1404 /*! \brief Return the current state of a member */
1405 static int get_queue_member_status(struct member *cur)
1407 return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
1410 /*! \brief allocate space for new queue member and set fields based on parameters passed */
1411 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
1415 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
1416 cur->penalty = penalty;
1417 cur->paused = paused;
1418 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
1419 if (!ast_strlen_zero(state_interface))
1420 ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
1422 ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
1423 if (!ast_strlen_zero(membername))
1424 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
1426 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
1427 if (!strchr(cur->interface, '/'))
1428 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
1429 if (!strncmp(cur->state_interface, "hint:", 5)) {
1430 char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
1431 char *exten = strsep(&context, "@") + 5;
1433 ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
1434 ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
1436 cur->status = get_queue_member_status(cur);
1443 static int compress_char(const char c)
1453 static int member_hash_fn(const void *obj, const int flags)
1455 const struct member *mem = obj;
1456 const char *chname = strchr(mem->interface, '/');
1459 chname = mem->interface;
1460 for (i = 0; i < 5 && chname[i]; i++)
1461 ret += compress_char(chname[i]) << (i * 6);
1465 static int member_cmp_fn(void *obj1, void *obj2, int flags)
1467 struct member *mem1 = obj1, *mem2 = obj2;
1468 return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH | CMP_STOP;
1472 * \brief Initialize Queue default values.
1473 * \note the queue's lock must be held before executing this function
1475 static void init_queue(struct call_queue *q)
1478 struct penalty_rule *pr_iter;
1481 q->retry = DEFAULT_RETRY;
1482 q->timeout = DEFAULT_TIMEOUT;
1484 q->announcefrequency = 0;
1485 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
1486 q->announceholdtime = 1;
1487 q->announcepositionlimit = 10; /* Default 10 positions */
1488 q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
1489 q->roundingseconds = 0; /* Default - don't announce seconds */
1490 q->servicelevel = 0;
1492 q->setinterfacevar = 0;
1494 q->setqueueentryvar = 0;
1495 q->autofill = autofill_default;
1496 q->montype = montype_default;
1497 q->monfmt[0] = '\0';
1498 q->reportholdtime = 0;
1500 q->penaltymemberslimit = 0;
1502 q->leavewhenempty = 0;
1504 q->maskmemberstatus = 0;
1505 q->eventwhencalled = 0;
1507 q->timeoutrestart = 0;
1508 q->periodicannouncefrequency = 0;
1509 q->randomperiodicannounce = 0;
1510 q->numperiodicannounce = 0;
1511 q->autopause = QUEUE_AUTOPAUSE_OFF;
1512 q->timeoutpriority = TIMEOUT_PRIORITY_APP;
1514 if (q->strategy == QUEUE_STRATEGY_LINEAR)
1515 /* linear strategy depends on order, so we have to place all members in a single bucket */
1516 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
1518 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
1522 ast_string_field_set(q, sound_next, "queue-youarenext");
1523 ast_string_field_set(q, sound_thereare, "queue-thereare");
1524 ast_string_field_set(q, sound_calls, "queue-callswaiting");
1525 ast_string_field_set(q, queue_quantity1, "queue-quantity1");
1526 ast_string_field_set(q, queue_quantity2, "queue-quantity2");
1527 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
1528 ast_string_field_set(q, sound_minutes, "queue-minutes");
1529 ast_string_field_set(q, sound_minute, "queue-minute");
1530 ast_string_field_set(q, sound_seconds, "queue-seconds");
1531 ast_string_field_set(q, sound_thanks, "queue-thankyou");
1532 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
1534 if ((q->sound_periodicannounce[0] = ast_str_create(32)))
1535 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
1537 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1538 if (q->sound_periodicannounce[i])
1539 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
1542 while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list)))
1546 static void clear_queue(struct call_queue *q)
1549 q->callscompleted = 0;
1550 q->callsabandoned = 0;
1551 q->callscompletedinsl = 0;
1556 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1557 while ((mem = ao2_iterator_next(&mem_iter))) {
1562 ao2_iterator_destroy(&mem_iter);
1567 * \brief Change queue penalty by adding rule.
1569 * Check rule for errors with time or fomatting, see if rule is relative to rest
1570 * of queue, iterate list of rules to find correct insertion point, insert and return.
1571 * \retval -1 on failure
1572 * \retval 0 on success
1573 * \note Call this with the rule_lists locked
1575 static int insert_penaltychange (const char *list_name, const char *content, const int linenum)
1577 char *timestr, *maxstr, *minstr, *contentdup;
1578 struct penalty_rule *rule = NULL, *rule_iter;
1579 struct rule_list *rl_iter;
1580 int penaltychangetime, inserted = 0;
1582 if (!(rule = ast_calloc(1, sizeof(*rule)))) {
1586 contentdup = ast_strdupa(content);
1588 if (!(maxstr = strchr(contentdup, ','))) {
1589 ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
1595 timestr = contentdup;
1597 if ((penaltychangetime = atoi(timestr)) < 0) {
1598 ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
1603 rule->time = penaltychangetime;
1605 if ((minstr = strchr(maxstr,',')))
1608 /* The last check will evaluate true if either no penalty change is indicated for a given rule
1609 * OR if a min penalty change is indicated but no max penalty change is */
1610 if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
1611 rule->max_relative = 1;
1614 rule->max_value = atoi(maxstr);
1616 if (!ast_strlen_zero(minstr)) {
1617 if (*minstr == '+' || *minstr == '-')
1618 rule->min_relative = 1;
1619 rule->min_value = atoi(minstr);
1620 } else /*there was no minimum specified, so assume this means no change*/
1621 rule->min_relative = 1;
1623 /*We have the rule made, now we need to insert it where it belongs*/
1624 AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
1625 if (strcasecmp(rl_iter->name, list_name))
1628 AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
1629 if (rule->time < rule_iter->time) {
1630 AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
1635 AST_LIST_TRAVERSE_SAFE_END;
1638 AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
1645 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
1647 char *value_copy = ast_strdupa(value);
1648 char *option = NULL;
1649 while ((option = strsep(&value_copy, ","))) {
1650 if (!strcasecmp(option, "paused")) {
1651 *empty |= QUEUE_EMPTY_PAUSED;
1652 } else if (!strcasecmp(option, "penalty")) {
1653 *empty |= QUEUE_EMPTY_PENALTY;
1654 } else if (!strcasecmp(option, "inuse")) {
1655 *empty |= QUEUE_EMPTY_INUSE;
1656 } else if (!strcasecmp(option, "ringing")) {
1657 *empty |= QUEUE_EMPTY_RINGING;
1658 } else if (!strcasecmp(option, "invalid")) {
1659 *empty |= QUEUE_EMPTY_INVALID;
1660 } else if (!strcasecmp(option, "wrapup")) {
1661 *empty |= QUEUE_EMPTY_WRAPUP;
1662 } else if (!strcasecmp(option, "unavailable")) {
1663 *empty |= QUEUE_EMPTY_UNAVAILABLE;
1664 } else if (!strcasecmp(option, "unknown")) {
1665 *empty |= QUEUE_EMPTY_UNKNOWN;
1666 } else if (!strcasecmp(option, "loose")) {
1667 *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
1668 } else if (!strcasecmp(option, "strict")) {
1669 *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
1670 } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
1671 *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
1672 } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
1675 ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
1680 /*! \brief Configure a queue parameter.
1682 * The failunknown flag is set for config files (and static realtime) to show
1683 * errors for unknown parameters. It is cleared for dynamic realtime to allow
1684 * extra fields in the tables.
1685 * \note For error reporting, line number is passed for .conf static configuration,
1686 * for Realtime queues, linenum is -1.
1688 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
1690 if (!strcasecmp(param, "musicclass") ||
1691 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
1692 ast_string_field_set(q, moh, val);
1693 } else if (!strcasecmp(param, "announce")) {
1694 ast_string_field_set(q, announce, val);
1695 } else if (!strcasecmp(param, "context")) {
1696 ast_string_field_set(q, context, val);
1697 } else if (!strcasecmp(param, "timeout")) {
1698 q->timeout = atoi(val);
1700 q->timeout = DEFAULT_TIMEOUT;
1701 } else if (!strcasecmp(param, "ringinuse")) {
1702 q->ringinuse = ast_true(val);
1703 } else if (!strcasecmp(param, "setinterfacevar")) {
1704 q->setinterfacevar = ast_true(val);
1705 } else if (!strcasecmp(param, "setqueuevar")) {
1706 q->setqueuevar = ast_true(val);
1707 } else if (!strcasecmp(param, "setqueueentryvar")) {
1708 q->setqueueentryvar = ast_true(val);
1709 } else if (!strcasecmp(param, "monitor-format")) {
1710 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
1711 } else if (!strcasecmp(param, "membermacro")) {
1712 ast_string_field_set(q, membermacro, val);
1713 } else if (!strcasecmp(param, "membergosub")) {
1714 ast_string_field_set(q, membergosub, val);
1715 } else if (!strcasecmp(param, "queue-youarenext")) {
1716 ast_string_field_set(q, sound_next, val);
1717 } else if (!strcasecmp(param, "queue-thereare")) {
1718 ast_string_field_set(q, sound_thereare, val);
1719 } else if (!strcasecmp(param, "queue-callswaiting")) {
1720 ast_string_field_set(q, sound_calls, val);
1721 } else if (!strcasecmp(param, "queue-quantity1")) {
1722 ast_string_field_set(q, queue_quantity1, val);
1723 } else if (!strcasecmp(param, "queue-quantity2")) {
1724 ast_string_field_set(q, queue_quantity2, val);
1725 } else if (!strcasecmp(param, "queue-holdtime")) {
1726 ast_string_field_set(q, sound_holdtime, val);
1727 } else if (!strcasecmp(param, "queue-minutes")) {
1728 ast_string_field_set(q, sound_minutes, val);
1729 } else if (!strcasecmp(param, "queue-minute")) {
1730 ast_string_field_set(q, sound_minute, val);
1731 } else if (!strcasecmp(param, "queue-seconds")) {
1732 ast_string_field_set(q, sound_seconds, val);
1733 } else if (!strcasecmp(param, "queue-thankyou")) {
1734 ast_string_field_set(q, sound_thanks, val);
1735 } else if (!strcasecmp(param, "queue-callerannounce")) {
1736 ast_string_field_set(q, sound_callerannounce, val);
1737 } else if (!strcasecmp(param, "queue-reporthold")) {
1738 ast_string_field_set(q, sound_reporthold, val);
1739 } else if (!strcasecmp(param, "announce-frequency")) {
1740 q->announcefrequency = atoi(val);
1741 } else if (!strcasecmp(param, "min-announce-frequency")) {
1742 q->minannouncefrequency = atoi(val);
1743 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
1744 } else if (!strcasecmp(param, "announce-round-seconds")) {
1745 q->roundingseconds = atoi(val);
1746 /* Rounding to any other values just doesn't make sense... */
1747 if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
1748 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
1750 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1751 "using 0 instead for queue '%s' at line %d of queues.conf\n",
1752 val, param, q->name, linenum);
1754 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1755 "using 0 instead for queue '%s'\n", val, param, q->name);
1757 q->roundingseconds=0;
1759 } else if (!strcasecmp(param, "announce-holdtime")) {
1760 if (!strcasecmp(val, "once"))
1761 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1762 else if (ast_true(val))
1763 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1765 q->announceholdtime = 0;
1766 } else if (!strcasecmp(param, "announce-position")) {
1767 if (!strcasecmp(val, "limit"))
1768 q->announceposition = ANNOUNCEPOSITION_LIMIT;
1769 else if (!strcasecmp(val, "more"))
1770 q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
1771 else if (ast_true(val))
1772 q->announceposition = ANNOUNCEPOSITION_YES;
1774 q->announceposition = ANNOUNCEPOSITION_NO;
1775 } else if (!strcasecmp(param, "announce-position-limit")) {
1776 q->announcepositionlimit = atoi(val);
1777 } else if (!strcasecmp(param, "periodic-announce")) {
1778 if (strchr(val, ',')) {
1779 char *s, *buf = ast_strdupa(val);
1782 while ((s = strsep(&buf, ",|"))) {
1783 if (!q->sound_periodicannounce[i])
1784 q->sound_periodicannounce[i] = ast_str_create(16);
1785 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
1787 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
1790 q->numperiodicannounce = i;
1792 ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
1793 q->numperiodicannounce = 1;
1795 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
1796 q->periodicannouncefrequency = atoi(val);
1797 } else if (!strcasecmp(param, "relative-periodic-announce")) {
1798 q->relativeperiodicannounce = ast_true(val);
1799 } else if (!strcasecmp(param, "random-periodic-announce")) {
1800 q->randomperiodicannounce = ast_true(val);
1801 } else if (!strcasecmp(param, "retry")) {
1802 q->retry = atoi(val);
1804 q->retry = DEFAULT_RETRY;
1805 } else if (!strcasecmp(param, "wrapuptime")) {
1806 q->wrapuptime = atoi(val);
1807 } else if (!strcasecmp(param, "penaltymemberslimit")) {
1808 if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
1809 q->penaltymemberslimit = 0;
1811 } else if (!strcasecmp(param, "autofill")) {
1812 q->autofill = ast_true(val);
1813 } else if (!strcasecmp(param, "monitor-type")) {
1814 if (!strcasecmp(val, "mixmonitor"))
1816 } else if (!strcasecmp(param, "autopause")) {
1817 q->autopause = autopause2int(val);
1818 } else if (!strcasecmp(param, "maxlen")) {
1819 q->maxlen = atoi(val);
1822 } else if (!strcasecmp(param, "servicelevel")) {
1823 q->servicelevel= atoi(val);
1824 } else if (!strcasecmp(param, "strategy")) {
1827 /* We are a static queue and already have set this, no need to do it again */
1831 strategy = strat2int(val);
1833 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
1835 q->strategy = QUEUE_STRATEGY_RINGALL;
1837 if (strategy == q->strategy) {
1840 if (strategy == QUEUE_STRATEGY_LINEAR) {
1841 ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
1844 q->strategy = strategy;
1845 } else if (!strcasecmp(param, "joinempty")) {
1846 parse_empty_options(val, &q->joinempty, 1);
1847 } else if (!strcasecmp(param, "leavewhenempty")) {
1848 parse_empty_options(val, &q->leavewhenempty, 0);
1849 } else if (!strcasecmp(param, "eventmemberstatus")) {
1850 q->maskmemberstatus = !ast_true(val);
1851 } else if (!strcasecmp(param, "eventwhencalled")) {
1852 if (!strcasecmp(val, "vars")) {
1853 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
1855 q->eventwhencalled = ast_true(val) ? 1 : 0;
1857 } else if (!strcasecmp(param, "reportholdtime")) {
1858 q->reportholdtime = ast_true(val);
1859 } else if (!strcasecmp(param, "memberdelay")) {
1860 q->memberdelay = atoi(val);
1861 } else if (!strcasecmp(param, "weight")) {
1862 q->weight = atoi(val);
1863 } else if (!strcasecmp(param, "timeoutrestart")) {
1864 q->timeoutrestart = ast_true(val);
1865 } else if (!strcasecmp(param, "defaultrule")) {
1866 ast_string_field_set(q, defaultrule, val);
1867 } else if (!strcasecmp(param, "timeoutpriority")) {
1868 if (!strcasecmp(val, "conf")) {
1869 q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
1871 q->timeoutpriority = TIMEOUT_PRIORITY_APP;
1873 } else if (failunknown) {
1875 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
1876 q->name, param, linenum);
1878 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
1884 * \brief Find rt member record to update otherwise create one.
1886 * Search for member in queue, if found update penalty/paused state,
1887 * if no member exists create one flag it as a RT member and add to queue member list.
1889 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface)
1892 struct ao2_iterator mem_iter;
1897 if (ast_strlen_zero(rt_uniqueid)) {
1898 ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
1903 penalty = atoi(penalty_str);
1909 paused = atoi(paused_str);
1914 /* Find member by realtime uniqueid and update */
1915 mem_iter = ao2_iterator_init(q->members, 0);
1916 while ((m = ao2_iterator_next(&mem_iter))) {
1917 if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
1918 m->dead = 0; /* Do not delete this one. */
1919 ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
1922 if (strcasecmp(state_interface, m->state_interface)) {
1923 ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
1925 m->penalty = penalty;
1932 ao2_iterator_destroy(&mem_iter);
1934 /* Create a new member */
1936 if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
1939 ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
1940 ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", "");
1941 ao2_link(q->members, m);
1949 /*! \brief Iterate through queue's member list and delete them */
1950 static void free_members(struct call_queue *q, int all)
1952 /* Free non-dynamic members */
1954 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1956 while ((cur = ao2_iterator_next(&mem_iter))) {
1957 if (all || !cur->dynamic) {
1958 ao2_unlink(q->members, cur);
1963 ao2_iterator_destroy(&mem_iter);
1966 /*! \brief Free queue's member list then its string fields */
1967 static void destroy_queue(void *obj)
1969 struct call_queue *q = obj;
1973 ast_string_field_free_memory(q);
1974 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1975 if (q->sound_periodicannounce[i])
1976 free(q->sound_periodicannounce[i]);
1978 ao2_ref(q->members, -1);
1981 static struct call_queue *alloc_queue(const char *queuename)
1983 struct call_queue *q;
1985 if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
1986 if (ast_string_field_init(q, 64)) {
1987 queue_t_unref(q, "String field allocation failed");
1990 ast_string_field_set(q, name, queuename);
1996 * \brief Reload a single queue via realtime.
1998 * Check for statically defined queue first, check if deleted RT queue,
1999 * check for new RT queue, if queue vars are not defined init them with defaults.
2000 * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
2001 * \retval the queue,
2002 * \retval NULL if it doesn't exist.
2003 * \note Should be called with the "queues" container locked.
2005 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
2007 struct ast_variable *v;
2008 struct call_queue *q, tmpq = {
2012 struct ao2_iterator mem_iter;
2013 char *interface = NULL;
2014 const char *tmp_name;
2016 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
2018 /* Static queues override realtime. */
2019 if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
2024 queue_t_unref(q, "Queue is dead; can't return it");
2027 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
2032 } else if (!member_config)
2033 /* Not found in the list, and it's not realtime ... */
2036 /* Check if queue is defined in realtime. */
2038 /* Delete queue from in-core list if it has been deleted in realtime. */
2040 /*! \note Hmm, can't seem to distinguish a DB failure from a not
2041 found condition... So we might delete an in-core queue
2042 in case of DB failure. */
2043 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
2046 /* Delete if unused (else will be deleted when last caller leaves). */
2047 queues_t_unlink(queues, q, "Unused; removing from container");
2049 queue_t_unref(q, "Queue is dead; can't return it");
2054 /* Create a new queue if an in-core entry does not exist yet. */
2056 struct ast_variable *tmpvar = NULL;
2057 if (!(q = alloc_queue(queuename)))
2063 /*Before we initialize the queue, we need to set the strategy, so that linear strategy
2064 * will allocate the members properly
2066 for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
2067 if (!strcasecmp(tmpvar->name, "strategy")) {
2068 q->strategy = strat2int(tmpvar->value);
2069 if (q->strategy < 0) {
2070 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
2071 tmpvar->value, q->name);
2072 q->strategy = QUEUE_STRATEGY_RINGALL;
2077 /* We traversed all variables and didn't find a strategy */
2079 q->strategy = QUEUE_STRATEGY_RINGALL;
2080 queues_t_link(queues, q, "Add queue to container");
2082 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
2084 memset(tmpbuf, 0, sizeof(tmpbuf));
2085 for (v = queue_vars; v; v = v->next) {
2086 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
2087 if ((tmp = strchr(v->name, '_'))) {
2088 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
2091 while ((tmp = strchr(tmp, '_')))
2096 if (!ast_strlen_zero(v->value)) {
2097 /* Don't want to try to set the option if the value is empty */
2098 queue_set_param(q, tmp_name, v->value, -1, 0);
2102 /* Temporarily set realtime members dead so we can detect deleted ones.
2103 * Also set the membercount correctly for realtime*/
2104 mem_iter = ao2_iterator_init(q->members, 0);
2105 while ((m = ao2_iterator_next(&mem_iter))) {
2111 ao2_iterator_destroy(&mem_iter);
2113 while ((interface = ast_category_browse(member_config, interface))) {
2114 rt_handle_member_record(q, interface,
2115 ast_variable_retrieve(member_config, interface, "uniqueid"),
2116 S_OR(ast_variable_retrieve(member_config, interface, "membername"),interface),
2117 ast_variable_retrieve(member_config, interface, "penalty"),
2118 ast_variable_retrieve(member_config, interface, "paused"),
2119 S_OR(ast_variable_retrieve(member_config, interface, "state_interface"),interface));
2122 /* Delete all realtime members that have been deleted in DB. */
2123 mem_iter = ao2_iterator_init(q->members, 0);
2124 while ((m = ao2_iterator_next(&mem_iter))) {
2126 ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
2127 ao2_unlink(q->members, m);
2132 ao2_iterator_destroy(&mem_iter);
2139 static struct call_queue *load_realtime_queue(const char *queuename)
2141 struct ast_variable *queue_vars;
2142 struct ast_config *member_config = NULL;
2143 struct call_queue *q = NULL, tmpq = {
2146 int prev_weight = 0;
2148 /* Find the queue in the in-core list first. */
2149 q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
2151 if (!q || q->realtime) {
2152 /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
2153 queue operations while waiting for the DB.
2155 This will be two separate database transactions, so we might
2156 see queue parameters as they were before another process
2157 changed the queue and member list as it was after the change.
2158 Thus we might see an empty member list when a queue is
2159 deleted. In practise, this is unlikely to cause a problem. */
2161 queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
2163 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
2164 if (!member_config) {
2165 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
2166 ast_variables_destroy(queue_vars);
2171 prev_weight = q->weight ? 1 : 0;
2176 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
2177 if (member_config) {
2178 ast_config_destroy(member_config);
2181 ast_variables_destroy(queue_vars);
2183 /* update the use_weight value if the queue's has gained or lost a weight */
2185 if (!q->weight && prev_weight) {
2186 ast_atomic_fetchadd_int(&use_weight, -1);
2188 if (q->weight && !prev_weight) {
2189 ast_atomic_fetchadd_int(&use_weight, +1);
2192 /* Other cases will end up with the proper value for use_weight */
2196 update_realtime_members(q);
2201 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
2205 if (ast_strlen_zero(mem->rt_uniqueid))
2208 if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0)
2215 static void update_realtime_members(struct call_queue *q)
2217 struct ast_config *member_config = NULL;
2219 char *interface = NULL;
2220 struct ao2_iterator mem_iter;
2222 if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
2223 /*This queue doesn't have realtime members*/
2224 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
2231 /* Temporarily set realtime members dead so we can detect deleted ones.*/
2232 mem_iter = ao2_iterator_init(q->members, 0);
2233 while ((m = ao2_iterator_next(&mem_iter))) {
2238 ao2_iterator_destroy(&mem_iter);
2240 while ((interface = ast_category_browse(member_config, interface))) {
2241 rt_handle_member_record(q, interface,
2242 ast_variable_retrieve(member_config, interface, "uniqueid"),
2243 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
2244 ast_variable_retrieve(member_config, interface, "penalty"),
2245 ast_variable_retrieve(member_config, interface, "paused"),
2246 S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface));
2249 /* Delete all realtime members that have been deleted in DB. */
2250 mem_iter = ao2_iterator_init(q->members, 0);
2251 while ((m = ao2_iterator_next(&mem_iter))) {
2253 ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
2254 ao2_unlink(q->members, m);
2259 ao2_iterator_destroy(&mem_iter);
2262 ast_config_destroy(member_config);
2265 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
2267 struct call_queue *q;
2268 struct queue_ent *cur, *prev = NULL;
2273 if (!(q = load_realtime_queue(queuename)))
2279 /* This is our one */
2282 if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) {
2283 *reason = QUEUE_JOINEMPTY;
2289 if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen))
2290 *reason = QUEUE_FULL;
2291 else if (*reason == QUEUE_UNKNOWN) {
2292 /* There's space for us, put us at the right position inside
2294 * Take into account the priority of the calling user */
2299 /* We have higher priority than the current user, enter
2300 * before him, after all the other users with priority
2301 * higher or equal to our priority. */
2302 if ((!inserted) && (qe->prio > cur->prio)) {
2303 insert_entry(q, prev, qe, &pos);
2306 /* <= is necessary for the position comparison because it may not be possible to enter
2307 * at our desired position since higher-priority callers may have taken the position we want
2309 if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
2310 insert_entry(q, prev, qe, &pos);
2311 /*pos is incremented inside insert_entry, so don't need to add 1 here*/
2312 if (position < pos) {
2313 ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
2321 /* No luck, join at the end of the queue */
2323 insert_entry(q, prev, qe, &pos);
2324 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
2325 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
2326 ast_copy_string(qe->context, q->context, sizeof(qe->context));
2329 ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
2330 "Channel: %s\r\nCallerIDNum: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
2332 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
2333 S_OR(qe->chan->cid.cid_name, "unknown"),
2334 q->name, qe->pos, q->count, qe->chan->uniqueid );
2335 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
2343 static int play_file(struct ast_channel *chan, const char *filename)
2347 if (ast_strlen_zero(filename)) {
2351 if (!ast_fileexists(filename, NULL, chan->language)) {
2355 ast_stopstream(chan);
2357 res = ast_streamfile(chan, filename, chan->language);
2359 res = ast_waitstream(chan, AST_DIGIT_ANY);
2361 ast_stopstream(chan);
2367 * \brief Check for valid exit from queue via goto
2368 * \retval 0 if failure
2369 * \retval 1 if successful
2371 static int valid_exit(struct queue_ent *qe, char digit)
2373 int digitlen = strlen(qe->digits);
2375 /* Prevent possible buffer overflow */
2376 if (digitlen < sizeof(qe->digits) - 2) {
2377 qe->digits[digitlen] = digit;
2378 qe->digits[digitlen + 1] = '\0';
2380 qe->digits[0] = '\0';
2384 /* If there's no context to goto, short-circuit */
2385 if (ast_strlen_zero(qe->context))
2388 /* If the extension is bad, then reset the digits to blank */
2389 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
2390 qe->digits[0] = '\0';
2394 /* We have an exact match */
2395 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
2396 qe->valid_digits = 1;
2397 /* Return 1 on a successful goto */
2404 static int say_position(struct queue_ent *qe, int ringing)
2406 int res = 0, avgholdmins, avgholdsecs, announceposition = 0;
2410 /* Let minannouncefrequency seconds pass between the start of each position announcement */
2412 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
2415 /* If either our position has changed, or we are over the freq timer, say position */
2416 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
2420 ast_indicate(qe->chan,-1);
2422 ast_moh_stop(qe->chan);
2425 if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
2426 qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
2427 (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
2428 qe->pos <= qe->parent->announcepositionlimit))
2429 announceposition = 1;
2432 if (announceposition == 1) {
2433 /* Say we're next, if we are */
2435 res = play_file(qe->chan, qe->parent->sound_next);
2441 if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
2443 res = play_file(qe->chan, qe->parent->queue_quantity1);
2446 res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
2451 res = play_file(qe->chan, qe->parent->sound_thereare);
2454 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
2458 if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
2460 res = play_file(qe->chan, qe->parent->queue_quantity2);
2464 res = play_file(qe->chan, qe->parent->sound_calls);
2470 /* Round hold time to nearest minute */
2471 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
2473 /* If they have specified a rounding then round the seconds as well */
2474 if (qe->parent->roundingseconds) {
2475 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
2476 avgholdsecs *= qe->parent->roundingseconds;
2481 ast_verb(3, "Hold time for %s is %d minute(s) %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
2483 /* If the hold time is >1 min, if it's enabled, and if it's not
2484 supposed to be only once and we have already said it, say it */
2485 if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
2486 ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
2487 !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
2488 res = play_file(qe->chan, qe->parent->sound_holdtime);
2492 if (avgholdmins >= 1) {
2493 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
2497 if (avgholdmins == 1) {
2498 res = play_file(qe->chan, qe->parent->sound_minute);
2502 res = play_file(qe->chan, qe->parent->sound_minutes);
2507 if (avgholdsecs >= 1) {
2508 res = ast_say_number(qe->chan, avgholdmins > 1 ? avgholdsecs : avgholdmins * 60 + avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
2512 res = play_file(qe->chan, qe->parent->sound_seconds);
2516 } else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
2521 if (qe->parent->announceposition) {
2522 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
2523 qe->chan->name, qe->parent->name, qe->pos);
2526 res = play_file(qe->chan, qe->parent->sound_thanks);
2530 if ((res > 0 && !valid_exit(qe, res)))
2533 /* Set our last_pos indicators */
2535 qe->last_pos_said = qe->pos;
2537 /* Don't restart music on hold if we're about to exit the caller from the queue */
2540 ast_indicate(qe->chan, AST_CONTROL_RINGING);
2542 ast_moh_start(qe->chan, qe->moh, NULL);
2548 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
2552 /* Calculate holdtime using an exponential average */
2553 /* Thanks to SRT for this contribution */
2554 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
2556 ao2_lock(qe->parent);
2557 oldvalue = qe->parent->holdtime;
2558 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
2559 ao2_unlock(qe->parent);
2562 /*! \brief Caller leaving queue.
2564 * Search the queue to find the leaving client, if found remove from queue
2565 * create manager event, move others up the queue.
2567 static void leave_queue(struct queue_ent *qe)
2569 struct call_queue *q;
2570 struct queue_ent *current, *prev = NULL;
2571 struct penalty_rule *pr_iter;
2574 if (!(q = qe->parent))
2576 queue_t_ref(q, "Copy queue pointer from queue entry");
2580 for (current = q->head; current; current = current->next) {
2581 if (current == qe) {
2585 /* Take us out of the queue */
2586 ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
2587 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
2588 qe->chan->name, q->name, q->count, qe->pos, qe->chan->uniqueid);
2589 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
2590 /* Take us out of the queue */
2592 prev->next = current->next;
2594 q->head = current->next;
2595 /* Free penalty rules */
2596 while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list)))
2598 snprintf(posstr, sizeof(posstr), "%d", qe->pos);
2599 pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
2601 /* Renumber the people after us in the queue based on a new count */
2602 current->pos = ++pos;
2608 /*If the queue is a realtime queue, check to see if it's still defined in real time*/
2610 struct ast_variable *var;
2611 if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
2614 ast_variables_destroy(var);
2619 /* It's dead and nobody is in it, so kill it */
2620 queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
2622 /* unref the explicit ref earlier in the function */
2623 queue_t_unref(q, "Expire copied reference");
2628 * \brief Destroy the given callattempt structure and free it.
2631 * \param doomed callattempt structure to destroy.
2635 static void callattempt_free(struct callattempt *doomed)
2637 if (doomed->member) {
2638 ao2_ref(doomed->member, -1);
2640 ast_party_connected_line_free(&doomed->connected);
2644 /*! \brief Hang up a list of outgoing calls */
2645 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
2647 struct callattempt *oo;
2650 /* If someone else answered the call we should indicate this in the CANCEL */
2651 /* Hangup any existing lines we have open */
2652 if (outgoing->chan && (outgoing->chan != exception)) {
2653 if (exception || cancel_answered_elsewhere)
2654 ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
2655 ast_hangup(outgoing->chan);
2658 outgoing = outgoing->q_next;
2659 ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
2660 callattempt_free(oo);
2665 * \brief Get the number of members available to accept a call.
2667 * \note The queue passed in should be locked prior to this function call
2669 * \param[in] q The queue for which we are couting the number of available members
2670 * \return Return the number of available members in queue q
2672 static int num_available_members(struct call_queue *q)
2676 struct ao2_iterator mem_iter;
2678 mem_iter = ao2_iterator_init(q->members, 0);
2679 while ((mem = ao2_iterator_next(&mem_iter))) {
2680 switch (mem->status) {
2681 case AST_DEVICE_INUSE:
2684 /* else fall through */
2685 case AST_DEVICE_NOT_INUSE:
2686 case AST_DEVICE_UNKNOWN:
2694 /* If autofill is not enabled or if the queue's strategy is ringall, then
2695 * we really don't care about the number of available members so much as we
2696 * do that there is at least one available.
2698 * In fact, we purposely will return from this function stating that only
2699 * one member is available if either of those conditions hold. That way,
2700 * functions which determine what action to take based on the number of available
2701 * members will operate properly. The reasoning is that even if multiple
2702 * members are available, only the head caller can actually be serviced.
2704 if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
2708 ao2_iterator_destroy(&mem_iter);
2713 /* traverse all defined queues which have calls waiting and contain this member
2714 return 0 if no other queue has precedence (higher weight) or 1 if found */
2715 static int compare_weight(struct call_queue *rq, struct member *member)
2717 struct call_queue *q;
2720 struct ao2_iterator queue_iter;
2722 /* q's lock and rq's lock already set by try_calling()
2723 * to solve deadlock */
2724 queue_iter = ao2_iterator_init(queues, 0);
2725 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
2726 if (q == rq) { /* don't check myself, could deadlock */
2727 queue_t_unref(q, "Done with iterator");
2731 if (q->count && q->members) {
2732 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
2733 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
2734 if (q->weight > rq->weight && q->count >= num_available_members(q)) {
2735 ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
2742 queue_t_unref(q, "Done with iterator");
2747 ao2_iterator_destroy(&queue_iter);
2751 /*! \brief common hangup actions */
2752 static void do_hang(struct callattempt *o)
2755 ast_hangup(o->chan);
2759 /*! \brief convert "\n" to "\nVariable: " ready for manager to use */
2760 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
2762 struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
2765 if (pbx_builtin_serialize_variables(chan, &buf)) {
2768 /* convert "\n" to "\nVariable: " */
2769 strcpy(vars, "Variable: ");
2770 tmp = ast_str_buffer(buf);
2772 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
2775 if (tmp[i + 1] == '\0')
2777 if (tmp[i] == '\n') {
2781 ast_copy_string(&(vars[j]), "Variable: ", len - j);
2791 /* there are no channel variables; leave it blank */
2798 * \brief Part 2 of ring_one
2800 * Does error checking before attempting to request a channel and call a member.
2801 * This function is only called from ring_one().
2802 * Failure can occur if:
2805 * - Wrapup time not expired
2806 * - Priority by another queue
2808 * \retval 1 on success to reach a free agent
2809 * \retval 0 on failure to get agent.
2811 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
2817 const char *macrocontext, *macroexten;
2819 /* on entry here, we know that tmp->chan == NULL */
2820 if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
2821 (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
2822 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
2823 (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
2825 ast_cdr_busy(qe->chan->cdr);
2826 tmp->stillgoing = 0;
2831 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
2832 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
2834 ast_cdr_busy(qe->chan->cdr);
2835 tmp->stillgoing = 0;
2839 if (tmp->member->paused) {
2840 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
2842 ast_cdr_busy(qe->chan->cdr);
2843 tmp->stillgoing = 0;
2846 if (use_weight && compare_weight(qe->parent,tmp->member)) {
2847 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
2849 ast_cdr_busy(qe->chan->cdr);
2850 tmp->stillgoing = 0;
2855 ast_copy_string(tech, tmp->interface, sizeof(tech));
2856 if ((location = strchr(tech, '/')))
2861 /* Request the peer */
2862 tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
2863 if (!tmp->chan) { /* If we can't, just go on to the next call */
2865 ast_cdr_busy(qe->chan->cdr);
2866 tmp->stillgoing = 0;
2868 ao2_lock(qe->parent);
2869 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
2870 qe->parent->rrpos++;
2872 ao2_unlock(qe->parent);
2878 ast_channel_lock(tmp->chan);
2879 while (ast_channel_trylock(qe->chan)) {
2880 CHANNEL_DEADLOCK_AVOIDANCE(tmp->chan);
2883 if (qe->cancel_answered_elsewhere) {
2884 ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
2886 tmp->chan->appl = "AppQueue";
2887 tmp->chan->data = "(Outgoing Line)";
2888 memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
2890 /* If the new channel has no callerid, try to guess what it should be */
2891 if (ast_strlen_zero(tmp->chan->cid.cid_num)) {
2892 if (!ast_strlen_zero(qe->chan->connected.id.number)) {
2893 ast_set_callerid(tmp->chan, qe->chan->connected.id.number, qe->chan->connected.id.name, qe->chan->connected.ani);
2894 tmp->chan->cid.cid_pres = qe->chan->connected.id.number_presentation;
2895 } else if (!ast_strlen_zero(qe->chan->cid.cid_dnid)) {
2896 ast_set_callerid(tmp->chan, qe->chan->cid.cid_dnid, NULL, NULL);
2897 } else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
2898 ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL);
2900 tmp->dial_callerid_absent = 1;
2903 ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
2905 tmp->chan->cid.cid_tns = qe->chan->cid.cid_tns;
2907 ast_connected_line_copy_from_caller(&tmp->chan->connected, &qe->chan->cid);
2909 /* Inherit specially named variables from parent channel */
2910 ast_channel_inherit_variables(qe->chan, tmp->chan);
2911 ast_channel_datastore_inherit(qe->chan, tmp->chan);
2913 /* Presense of ADSI CPE on outgoing channel follows ours */
2914 tmp->chan->adsicpe = qe->chan->adsicpe;
2916 /* Inherit context and extension */
2917 macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
2918 ast_string_field_set(tmp->chan, dialcontext, ast_strlen_zero(macrocontext) ? qe->chan->context : macrocontext);
2919 macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
2920 if (!ast_strlen_zero(macroexten))
2921 ast_copy_string(tmp->chan->exten, macroexten, sizeof(tmp->chan->exten));
2923 ast_copy_string(tmp->chan->exten, qe->chan->exten, sizeof(tmp->chan->exten));
2924 if (ast_cdr_isset_unanswered()) {
2925 /* they want to see the unanswered dial attempts! */
2926 /* set up the CDR fields on all the CDRs to give sensical information */
2927 ast_cdr_setdestchan(tmp->chan->cdr, tmp->chan->name);
2928 strcpy(tmp->chan->cdr->clid, qe->chan->cdr->clid);
2929 strcpy(tmp->chan->cdr->channel, qe->chan->cdr->channel);
2930 strcpy(tmp->chan->cdr->src, qe->chan->cdr->src);
2931 strcpy(tmp->chan->cdr->dst, qe->chan->exten);
2932 strcpy(tmp->chan->cdr->dcontext, qe->chan->context);
2933 strcpy(tmp->chan->cdr->lastapp, qe->chan->cdr->lastapp);
2934 strcpy(tmp->chan->cdr->lastdata, qe->chan->cdr->lastdata);
2935 tmp->chan->cdr->amaflags = qe->chan->cdr->amaflags;
2936 strcpy(tmp->chan->cdr->accountcode, qe->chan->cdr->accountcode);
2937 strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
2940 /* Place the call, but don't wait on the answer */
2941 if ((res = ast_call(tmp->chan, location, 0))) {
2942 /* Again, keep going even if there's an error */
2943 ast_debug(1, "ast call on peer returned %d\n", res);
2944 ast_verb(3, "Couldn't call %s\n", tmp->interface);
2945 ast_channel_unlock(tmp->chan);
2946 ast_channel_unlock(qe->chan);
2949 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
2951 } else if (qe->parent->eventwhencalled) {
2954 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
2956 "AgentCalled: %s\r\n"
2958 "ChannelCalling: %s\r\n"
2959 "DestinationChannel: %s\r\n"
2960 "CallerIDNum: %s\r\n"
2961 "CallerIDName: %s\r\n"
2967 qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
2968 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
2969 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
2970 qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
2971 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2972 ast_verb(3, "Called %s\n", tmp->interface);
2974 ast_channel_unlock(tmp->chan);
2975 ast_channel_unlock(qe->chan);
2977 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
2981 /*! \brief find the entry with the best metric, or NULL */
2982 static struct callattempt *find_best(struct callattempt *outgoing)
2984 struct callattempt *best = NULL, *cur;
2986 for (cur = outgoing; cur; cur = cur->q_next) {
2987 if (cur->stillgoing && /* Not already done */
2988 !cur->chan && /* Isn't already going */
2989 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
2998 * \brief Place a call to a queue member.
3000 * Once metrics have been calculated for each member, this function is used
3001 * to place a call to the appropriate member (or members). The low-level
3002 * channel-handling and error detection is handled in ring_entry
3004 * \retval 1 if a member was called successfully
3005 * \retval 0 otherwise
3007 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
3012 struct callattempt *best = find_best(outgoing);
3014 ast_debug(1, "Nobody left to try ringing in queue\n");
3017 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
3018 struct callattempt *cur;
3019 /* Ring everyone who shares this best metric (for ringall) */
3020 for (cur = outgoing; cur; cur = cur->q_next) {
3021 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
3022 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
3023 ret |= ring_entry(qe, cur, busies);
3027 /* Ring just the best channel */
3028 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
3029 ret = ring_entry(qe, best, busies);
3032 /* If we have timed out, break out */
3033 if (qe->expire && (time(NULL) >= qe->expire)) {
3034 ast_debug(1, "Queue timed out while ringing members.\n");
3043 /*! \brief Search for best metric and add to Round Robbin queue */
3044 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
3046 struct callattempt *best = find_best(outgoing);
3049 /* Ring just the best channel */
3050 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
3051 qe->parent->rrpos = best->metric % 1000;
3053 /* Just increment rrpos */
3054 if (qe->parent->wrapped) {
3055 /* No more channels, start over */
3056 qe->parent->rrpos = 0;
3058 /* Prioritize next entry */
3059 qe->parent->rrpos++;
3062 qe->parent->wrapped = 0;
3067 /*! \brief Search for best metric and add to Linear queue */
3068 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
3070 struct callattempt *best = find_best(outgoing);
3073 /* Ring just the best channel */
3074 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
3075 qe->linpos = best->metric % 1000;
3077 /* Just increment rrpos */
3078 if (qe->linwrapped) {
3079 /* No more channels, start over */
3082 /* Prioritize next entry */
3091 /*! \brief Playback announcement to queued members if peroid has elapsed */
3092 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
3097 /* Get the current time */
3100 /* Check to see if it is time to announce */
3101 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
3104 /* Stop the music on hold so we can play our own file */
3106 ast_indicate(qe->chan,-1);
3108 ast_moh_stop(qe->chan);
3110 ast_verb(3, "Playing periodic announcement\n");
3112 if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
3113 qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
3114 } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
3115 ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
3116 qe->last_periodic_announce_sound = 0;
3119 /* play the announcement */
3120 res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
3122 if (res > 0 && !valid_exit(qe, res))
3125 /* Resume Music on Hold if the caller is going to stay in the queue */
3128 ast_indicate(qe->chan, AST_CONTROL_RINGING);
3130 ast_moh_start(qe->chan, qe->moh, NULL);
3133 /* update last_periodic_announce_time */
3134 if (qe->parent->relativeperiodicannounce)
3135 time(&qe->last_periodic_announce_time);
3137 qe->last_periodic_announce_time = now;
3139 /* Update the current periodic announcement to the next announcement */
3140 if (!qe->parent->randomperiodicannounce) {
3141 qe->last_periodic_announce_sound++;
3147 /*! \brief Record that a caller gave up on waiting in queue */
3148 static void record_abandoned(struct queue_ent *qe)
3150 ao2_lock(qe->parent);
3151 set_queue_variables(qe->parent, qe->chan);
3152 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
3156 "OriginalPosition: %d\r\n"
3158 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
3160 qe->parent->callsabandoned++;
3161 ao2_unlock(qe->parent);
3164 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
3165 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int pause)
3167 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
3169 /* Stop ringing, and resume MOH if specified */
3170 if (qe->ring_when_ringing) {
3171 ast_indicate(qe->chan, -1);
3172 ast_moh_start(qe->chan, qe->moh, NULL);
3175 if (qe->parent->eventwhencalled) {
3178 manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
3183 "MemberName: %s\r\n"
3192 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3194 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
3195 if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && pause) {
3196 if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
3197 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
3198 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
3199 interface, qe->parent->name);
3201 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
3204 /* If queue autopause is mode all, just don't send any queue to stop.
3205 * the function will stop in all queues */
3206 if (!set_member_paused("", interface, "Auto-Pause", 1)) {
3207 ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
3208 interface, qe->parent->name);
3210 ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
3217 #define AST_MAX_WATCHERS 256
3219 * \brief Wait for a member to answer the call
3221 * \param[in] qe the queue_ent corresponding to the caller in the queue
3222 * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
3223 * \param[in] to the amount of time (in milliseconds) to wait for a response
3224 * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
3225 * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
3226 * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
3227 * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
3228 * \param[in] update_connectedline Allow connected line and redirecting updates to pass through.
3230 * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
3232 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline)
3234 const char *queue = qe->parent->name;
3235 struct callattempt *o, *start = NULL, *prev = NULL;
3238 int numbusies = prebusies;
3242 struct ast_frame *f;
3243 struct callattempt *peer = NULL;
3244 struct ast_channel *winner;
3245 struct ast_channel *in = qe->chan;
3247 char membername[80] = "";
3251 struct callattempt *epollo;
3253 struct ast_party_connected_line connected_caller;
3256 ast_party_connected_line_init(&connected_caller);
3258 ast_channel_lock(qe->chan);
3259 inchan_name = ast_strdupa(qe->chan->name);
3260 ast_channel_unlock(qe->chan);
3262 starttime = (long) time(NULL);
3264 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
3266 ast_poll_channel_add(in, epollo->chan);
3270 while (*to && !peer) {
3271 int numlines, retry, pos = 1;
3272 struct ast_channel *watchers[AST_MAX_WATCHERS];
3276 for (retry = 0; retry < 2; retry++) {
3278 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
3279 if (o->stillgoing) { /* Keep track of important channels */
3282 watchers[pos++] = o->chan;
3286 prev->call_next = o;
3292 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
3293 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
3295 /* On "ringall" strategy we only move to the next penalty level
3296 when *all* ringing phones are done in the current penalty level */
3297 ring_one(qe, outgoing, &numbusies);
3300 if (pos == 1 /* not found */) {
3301 if (numlines == (numbusies + numnochan)) {
3302 ast_debug(1, "Everyone is busy at this time\n");
3304 ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
3310 /* Poll for events from both the incoming channel as well as any outgoing channels */
3311 winner = ast_waitfor_n(watchers, pos, to);
3313 /* Service all of the outgoing channels */
3314 for (o = start; o; o = o->call_next) {
3315 /* We go with a static buffer here instead of using ast_strdupa. Using
3316 * ast_strdupa in a loop like this one can cause a stack overflow
3318 char ochan_name[AST_CHANNEL_NAME];
3320 ast_channel_lock(o->chan);
3321 ast_copy_string(ochan_name, o->chan->name, sizeof(ochan_name));
3322 ast_channel_unlock(o->chan);
3324 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
3326 ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
3327 if (update_connectedline) {
3328 if (o->pending_connected_update) {
3329 if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
3330 ast_channel_update_connected_line(in, &o->connected);
3332 } else if (!o->dial_callerid_absent) {
3333 ast_channel_lock(o->chan);
3334 ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
3335 ast_channel_unlock(o->chan);
3336 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
3337 ast_channel_update_connected_line(in, &connected_caller);
3338 ast_party_connected_line_free(&connected_caller);
3341 if (o->aoc_s_rate_list) {
3342 size_t encoded_size;
3343 struct ast_aoc_encoded *encoded;
3344 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
3345 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
3346 ast_aoc_destroy_encoded(encoded);
3351 } else if (o->chan && (o->chan == winner)) {
3353 ast_copy_string(on, o->member->interface, sizeof(on));
3354 ast_copy_string(membername, o->member->membername, sizeof(membername));