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>
71 #include "asterisk/lock.h"
72 #include "asterisk/file.h"
73 #include "asterisk/channel.h"
74 #include "asterisk/pbx.h"
75 #include "asterisk/app.h"
76 #include "asterisk/linkedlists.h"
77 #include "asterisk/module.h"
78 #include "asterisk/translate.h"
79 #include "asterisk/say.h"
80 #include "asterisk/features.h"
81 #include "asterisk/musiconhold.h"
82 #include "asterisk/cli.h"
83 #include "asterisk/manager.h"
84 #include "asterisk/config.h"
85 #include "asterisk/monitor.h"
86 #include "asterisk/utils.h"
87 #include "asterisk/causes.h"
88 #include "asterisk/astdb.h"
89 #include "asterisk/devicestate.h"
90 #include "asterisk/stringfields.h"
91 #include "asterisk/event.h"
92 #include "asterisk/astobj2.h"
93 #include "asterisk/strings.h"
94 #include "asterisk/global_datastores.h"
95 #include "asterisk/taskprocessor.h"
98 * \par Please read before modifying this file.
99 * There are three locks which are regularly used
100 * throughout this file, the queue list lock, the lock
101 * for each individual queue, and the interface list lock.
102 * Please be extra careful to always lock in the following order
104 * 2) individual queue lock
105 * 3) interface list lock
106 * This order has sort of "evolved" over the lifetime of this
107 * application, but it is now in place this way, so please adhere
113 QUEUE_STRATEGY_RINGALL = 0,
114 QUEUE_STRATEGY_LEASTRECENT,
115 QUEUE_STRATEGY_FEWESTCALLS,
116 QUEUE_STRATEGY_RANDOM,
117 QUEUE_STRATEGY_RRMEMORY,
118 QUEUE_STRATEGY_LINEAR,
119 QUEUE_STRATEGY_WRANDOM
122 static const struct strategy {
126 { QUEUE_STRATEGY_RINGALL, "ringall" },
127 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
128 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
129 { QUEUE_STRATEGY_RANDOM, "random" },
130 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
131 { QUEUE_STRATEGY_LINEAR, "linear" },
132 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
135 static struct ast_taskprocessor *devicestate_tps;
137 #define DEFAULT_RETRY 5
138 #define DEFAULT_TIMEOUT 15
139 #define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
140 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
141 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /*!< The minimum number of seconds between position announcements \
142 The default value of 15 provides backwards compatibility */
143 #define MAX_QUEUE_BUCKETS 53
145 #define RES_OKAY 0 /*!< Action completed */
146 #define RES_EXISTS (-1) /*!< Entry already exists */
147 #define RES_OUTOFMEMORY (-2) /*!< Out of memory */
148 #define RES_NOSUCHQUEUE (-3) /*!< No such queue */
149 #define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
151 static char *app = "Queue";
153 static char *synopsis = "Queue a call for a call queue";
155 static char *descrip =
156 " Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub][,rule]):\n"
157 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
158 "This application will return to the dialplan if the queue does not exist, or\n"
159 "any of the join options cause the caller to not enter the queue.\n"
160 "The option string may contain zero or more of the following characters:\n"
161 " 'c' -- continue in the dialplan if the callee hangs up.\n"
162 " 'd' -- data-quality (modem) call (minimum delay).\n"
163 " 'h' -- allow callee to hang up by pressing *.\n"
164 " 'H' -- allow caller to hang up by pressing *.\n"
165 " 'n' -- no retries on the timeout; will exit this application and \n"
166 " go to the next step.\n"
167 " 'i' -- ignore call forward requests from queue members and do nothing\n"
168 " when they are requested.\n"
169 " 'r' -- ring instead of playing MOH. Periodic Announcements are still made, if applicable.\n"
170 " 't' -- allow the called user to transfer the calling user.\n"
171 " 'T' -- allow the calling user to transfer the call.\n"
172 " 'w' -- allow the called user to write the conversation to disk via Monitor.\n"
173 " 'W' -- allow the calling user to write the conversation to disk via Monitor.\n"
174 " 'k' -- Allow the called party to enable parking of the call by sending\n"
175 " the DTMF sequence defined for call parking in features.conf.\n"
176 " 'K' -- Allow the calling party to enable parking of the call by sending\n"
177 " the DTMF sequence defined for call parking in features.conf.\n"
178 " 'x' -- allow the called user to write the conversation to disk via MixMonitor\n"
179 " 'X' -- allow the calling user to write the conversation to disk via MixMonitor\n"
181 " In addition to transferring the call, a call may be parked and then picked\n"
182 "up by another user.\n"
183 " The optional URL will be sent to the called party if the channel supports\n"
185 " The optional AGI parameter will setup an AGI script to be executed on the \n"
186 "calling party's channel once they are connected to a queue member.\n"
187 " The optional macro parameter will run a macro on the \n"
188 "calling party's channel once they are connected to a queue member.\n"
189 " The optional gosub parameter will run a gosub on the \n"
190 "calling party's channel once they are connected to a queue member.\n"
191 " The optional rule parameter will cause the queue's defaultrule to be\n"
192 "overridden by the rule specified.\n"
193 " The timeout will cause the queue to fail out after a specified number of\n"
194 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
195 " This application sets the following channel variable upon completion:\n"
196 " QUEUESTATUS The status of the call as a text string, one of\n"
197 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\n";
199 static char *app_aqm = "AddQueueMember" ;
200 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
201 static char *app_aqm_descrip =
202 " AddQueueMember(queuename[,interface[,penalty[,options[,membername]]]]):\n"
203 "Dynamically adds interface to an existing queue.\n"
204 "If the interface is already in the queue it will return an error.\n"
205 " This application sets the following channel variable upon completion:\n"
206 " AQMSTATUS The status of the attempt to add a queue member as a \n"
207 " text string, one of\n"
208 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
209 "Example: AddQueueMember(techsupport,SIP/3000)\n"
212 static char *app_rqm = "RemoveQueueMember" ;
213 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
214 static char *app_rqm_descrip =
215 " RemoveQueueMember(queuename[,interface[,options]]):\n"
216 "Dynamically removes interface to an existing queue\n"
217 "If the interface is NOT in the queue it will return an error.\n"
218 " This application sets the following channel variable upon completion:\n"
219 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
220 " text string, one of\n"
221 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
222 "Example: RemoveQueueMember(techsupport,SIP/3000)\n"
225 static char *app_pqm = "PauseQueueMember" ;
226 static char *app_pqm_synopsis = "Pauses a queue member" ;
227 static char *app_pqm_descrip =
228 " PauseQueueMember([queuename],interface[,options[,reason]]):\n"
229 "Pauses (blocks calls for) a queue member.\n"
230 "The given interface will be paused in the given queue. This prevents\n"
231 "any calls from being sent from the queue to the interface until it is\n"
232 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
233 "queuename is given, the interface is paused in every queue it is a\n"
234 "member of. The application will fail if the interface is not found.\n"
235 "The reason string is entirely optional and is used to add extra information\n"
236 "to the appropriate queue_log entries and manager events.\n"
237 " This application sets the following channel variable upon completion:\n"
238 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
239 " text string, one of\n"
240 " PAUSED | NOTFOUND\n"
241 "Example: PauseQueueMember(,SIP/3000)\n";
243 static char *app_upqm = "UnpauseQueueMember" ;
244 static char *app_upqm_synopsis = "Unpauses a queue member" ;
245 static char *app_upqm_descrip =
246 " UnpauseQueueMember([queuename],interface[,options[,reason]]):\n"
247 "Unpauses (resumes calls to) a queue member.\n"
248 "This is the counterpart to PauseQueueMember and operates exactly the\n"
249 "same way, except it unpauses instead of pausing the given interface.\n"
250 "The reason string is entirely optional and is used to add extra information\n"
251 "to the appropriate queue_log entries and manager events.\n"
252 " This application sets the following channel variable upon completion:\n"
253 " UPQMSTATUS The status of the attempt to unpause a queue \n"
254 " member as a text string, one of\n"
255 " UNPAUSED | NOTFOUND\n"
256 "Example: UnpauseQueueMember(,SIP/3000)\n";
258 static char *app_ql = "QueueLog" ;
259 static char *app_ql_synopsis = "Writes to the queue_log" ;
260 static char *app_ql_descrip =
261 " QueueLog(queuename,uniqueid,agent,event[,additionalinfo]):\n"
262 "Allows you to write your own events into the queue log\n"
263 "Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)\n";
265 /*! \brief Persistent Members astdb family */
266 static const char *pm_family = "Queue/PersistentMembers";
267 /* The maximum length of each persistent member queue database entry */
268 #define PM_MAX_LEN 8192
270 /*! \brief queues.conf [general] option */
271 static int queue_keep_stats = 0;
273 /*! \brief queues.conf [general] option */
274 static int queue_persistent_members = 0;
276 /*! \brief queues.conf per-queue weight option */
277 static int use_weight = 0;
279 /*! \brief queues.conf [general] option */
280 static int autofill_default = 0;
282 /*! \brief queues.conf [general] option */
283 static int montype_default = 0;
285 /*! \brief queues.conf [general] option */
286 static int shared_lastcall = 0;
288 /*! \brief Subscription to device state change events */
289 static struct ast_event_sub *device_state_sub;
291 /*! \brief queues.conf [general] option */
292 static int update_cdr = 0;
298 QUEUE_LEAVEEMPTY = 3,
299 QUEUE_JOINUNAVAIL = 4,
300 QUEUE_LEAVEUNAVAIL = 5,
306 enum queue_result id;
308 } queue_results[] = {
309 { QUEUE_UNKNOWN, "UNKNOWN" },
310 { QUEUE_TIMEOUT, "TIMEOUT" },
311 { QUEUE_JOINEMPTY,"JOINEMPTY" },
312 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
313 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
314 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
315 { QUEUE_FULL, "FULL" },
316 { QUEUE_CONTINUE, "CONTINUE" },
319 /*! \brief We define a custom "local user" structure because we
320 * use it not only for keeping track of what is in use but
321 * also for keeping track of who we're dialing.
323 * There are two "links" defined in this structure, q_next and call_next.
324 * q_next links ALL defined callattempt structures into a linked list. call_next is
325 * a link which allows for a subset of the callattempts to be traversed. This subset
326 * is used in wait_for_answer so that irrelevant callattempts are not traversed. This
327 * also is helpful so that queue logs are always accurate in the case where a call to
328 * a member times out, especially if using the ringall strategy.
332 struct callattempt *q_next;
333 struct callattempt *call_next;
334 struct ast_channel *chan;
340 struct call_queue *lastqueue;
341 struct member *member;
346 struct call_queue *parent; /*!< What queue is our parent */
347 char moh[80]; /*!< Name of musiconhold to be used */
348 char announce[80]; /*!< Announcement to play for member when call is answered */
349 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
350 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
351 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
352 int pos; /*!< Where we are in the queue */
353 int prio; /*!< Our priority */
354 int last_pos_said; /*!< Last position we told the user */
355 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
356 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
357 time_t last_pos; /*!< Last time we told the user their position */
358 int opos; /*!< Where we started in the queue */
359 int handled; /*!< Whether our call was handled */
360 int pending; /*!< Non-zero if we are attempting to call a member */
361 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
362 int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
363 int linpos; /*!< If using linear strategy, what position are we at? */
364 int linwrapped; /*!< Is the linpos wrapped? */
365 time_t start; /*!< When we started holding */
366 time_t expire; /*!< When this entry should expire (time out of queue) */
367 struct ast_channel *chan; /*!< Our channel */
368 AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
369 struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
370 struct queue_ent *next; /*!< The next queue entry */
374 char interface[80]; /*!< Technology/Location to dial to reach this member*/
375 char state_interface[80]; /*!< Technology/Location from which to read devicestate changes */
376 char membername[80]; /*!< Member name to use in queue logs */
377 int penalty; /*!< Are we a last resort? */
378 int calls; /*!< Number of calls serviced by this member */
379 int dynamic; /*!< Are we dynamically added? */
380 int realtime; /*!< Is this member realtime? */
381 int status; /*!< Status of queue member */
382 int paused; /*!< Are we paused (not accepting calls)? */
383 time_t lastcall; /*!< When last successful call was hungup */
384 struct call_queue *lastqueue; /*!< Last queue we received a call */
385 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
386 unsigned int delme:1; /*!< Flag to delete entry on reload */
389 struct member_interface {
391 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
394 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
396 /* values used in multi-bit flags in call_queue */
397 #define QUEUE_EMPTY_NORMAL 1
398 #define QUEUE_EMPTY_STRICT 2
399 #define QUEUE_EMPTY_LOOSE 3
400 #define ANNOUNCEHOLDTIME_ALWAYS 1
401 #define ANNOUNCEHOLDTIME_ONCE 2
402 #define QUEUE_EVENT_VARIABLES 3
404 struct penalty_rule {
405 int time; /*!< Number of seconds that need to pass before applying this rule */
406 int max_value; /*!< The amount specified in the penalty rule for max penalty */
407 int min_value; /*!< The amount specified in the penalty rule for min penalty */
408 int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
409 int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
410 AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
413 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
414 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
415 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
416 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
419 AST_DECLARE_STRING_FIELDS(
421 AST_STRING_FIELD(name);
422 /*! Music on Hold class */
423 AST_STRING_FIELD(moh);
424 /*! Announcement to play when call is answered */
425 AST_STRING_FIELD(announce);
427 AST_STRING_FIELD(context);
428 /*! Macro to run upon member connection */
429 AST_STRING_FIELD(membermacro);
430 /*! Gosub to run upon member connection */
431 AST_STRING_FIELD(membergosub);
432 /*! Default rule to use if none specified in call to Queue() */
433 AST_STRING_FIELD(defaultrule);
434 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
435 AST_STRING_FIELD(sound_next);
436 /*! Sound file: "There are currently" (def. queue-thereare) */
437 AST_STRING_FIELD(sound_thereare);
438 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
439 AST_STRING_FIELD(sound_calls);
440 /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
441 AST_STRING_FIELD(queue_quantity1);
442 /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
443 AST_STRING_FIELD(queue_quantity2);
444 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
445 AST_STRING_FIELD(sound_holdtime);
446 /*! Sound file: "minutes." (def. queue-minutes) */
447 AST_STRING_FIELD(sound_minutes);
448 /*! Sound file: "minute." (def. queue-minute) */
449 AST_STRING_FIELD(sound_minute);
450 /*! Sound file: "seconds." (def. queue-seconds) */
451 AST_STRING_FIELD(sound_seconds);
452 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
453 AST_STRING_FIELD(sound_thanks);
454 /*! Sound file: Custom announce for caller, no default */
455 AST_STRING_FIELD(sound_callerannounce);
456 /*! Sound file: "Hold time" (def. queue-reporthold) */
457 AST_STRING_FIELD(sound_reporthold);
459 /*! Sound files: Custom announce, no default */
460 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
462 unsigned int joinempty:2;
463 unsigned int eventwhencalled:2;
464 unsigned int leavewhenempty:2;
465 unsigned int ringinuse:1;
466 unsigned int setinterfacevar:1;
467 unsigned int setqueuevar:1;
468 unsigned int setqueueentryvar:1;
469 unsigned int reportholdtime:1;
470 unsigned int wrapped:1;
471 unsigned int timeoutrestart:1;
472 unsigned int announceholdtime:2;
473 unsigned int announceposition:3;
475 unsigned int maskmemberstatus:1;
476 unsigned int realtime:1;
477 unsigned int found:1;
478 int announcepositionlimit; /*!< How many positions we announce? */
479 int announcefrequency; /*!< How often to announce their position */
480 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
481 int periodicannouncefrequency; /*!< How often to play periodic announcement */
482 int numperiodicannounce; /*!< The number of periodic announcements configured */
483 int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
484 int roundingseconds; /*!< How many seconds do we round to? */
485 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
486 int callscompleted; /*!< Number of queue calls completed */
487 int callsabandoned; /*!< Number of queue calls abandoned */
488 int servicelevel; /*!< seconds setting for servicelevel*/
489 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
490 char monfmt[8]; /*!< Format to use when recording calls */
491 int montype; /*!< Monitor type Monitor vs. MixMonitor */
492 int count; /*!< How many entries */
493 int maxlen; /*!< Max number of entries */
494 int wrapuptime; /*!< Wrapup Time */
496 int retry; /*!< Retry calling everyone after this amount of time */
497 int timeout; /*!< How long to wait for an answer */
498 int weight; /*!< Respective weight */
499 int autopause; /*!< Auto pause queue members if they fail to answer */
501 /* Queue strategy things */
502 int rrpos; /*!< Round Robin - position */
503 int memberdelay; /*!< Seconds to delay connecting member to caller */
504 int autofill; /*!< Ignore the head call status and ring an available agent */
506 struct ao2_container *members; /*!< Head of the list of members */
508 * \brief Number of members _logged in_
509 * \note There will be members in the members container that are not logged
510 * in, so this can not simply be replaced with ao2_container_count().
513 struct queue_ent *head; /*!< Head of the list of callers */
514 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
515 AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
520 AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
521 AST_LIST_ENTRY(rule_list) list;
524 AST_LIST_HEAD_STATIC(rule_lists, rule_list);
526 static struct ao2_container *queues;
528 static void update_realtime_members(struct call_queue *q);
529 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
531 /*! \brief sets the QUEUESTATUS channel variable */
532 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
536 for (i = 0; i < ARRAY_LEN(queue_results); i++) {
537 if (queue_results[i].id == res) {
538 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
544 static const char *int2strat(int strategy)
548 for (x = 0; x < ARRAY_LEN(strategies); x++) {
549 if (strategy == strategies[x].strategy)
550 return strategies[x].name;
556 static int strat2int(const char *strategy)
560 for (x = 0; x < ARRAY_LEN(strategies); x++) {
561 if (!strcasecmp(strategy, strategies[x].name))
562 return strategies[x].strategy;
568 static int queue_hash_cb(const void *obj, const int flags)
570 const struct call_queue *q = obj;
571 return ast_str_hash(q->name);
574 static int queue_cmp_cb(void *obj, void *arg, int flags)
576 struct call_queue *q = obj, *q2 = arg;
577 return !strcasecmp(q->name, q2->name) ? CMP_MATCH : 0;
580 static inline struct call_queue *queue_ref(struct call_queue *q)
586 static inline struct call_queue *queue_unref(struct call_queue *q)
592 /*! \brief Set variables of queue */
593 static void set_queue_variables(struct queue_ent *qe)
595 char interfacevar[256]="";
598 if (qe->parent->setqueuevar) {
600 if (qe->parent->callscompleted > 0)
601 sl = 100 * ((float) qe->parent->callscompletedinsl / (float) qe->parent->callscompleted);
603 snprintf(interfacevar, sizeof(interfacevar),
604 "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
605 qe->parent->name, qe->parent->maxlen, int2strat(qe->parent->strategy), qe->parent->count, qe->parent->holdtime, qe->parent->callscompleted,
606 qe->parent->callsabandoned, qe->parent->servicelevel, sl);
608 pbx_builtin_setvar_multiple(qe->chan, interfacevar);
612 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
613 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
615 struct queue_ent *cur;
632 enum queue_member_status {
634 QUEUE_NO_REACHABLE_MEMBERS,
635 QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
639 /*! \brief Check if members are available
641 * This function checks to see if members are available to be called. If any member
642 * is available, the function immediately returns QUEUE_NORMAL. If no members are available,
643 * the appropriate reason why is returned
645 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty, int min_penalty)
647 struct member *member;
648 struct ao2_iterator mem_iter;
649 enum queue_member_status result = QUEUE_NO_MEMBERS;
652 mem_iter = ao2_iterator_init(q->members, 0);
653 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
654 if ((max_penalty && (member->penalty > max_penalty)) || (min_penalty && (member->penalty < min_penalty)))
657 switch (member->status) {
658 case AST_DEVICE_INVALID:
661 case AST_DEVICE_UNAVAILABLE:
662 if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)
663 result = QUEUE_NO_REACHABLE_MEMBERS;
666 if (member->paused) {
667 result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
682 AST_LIST_ENTRY(statechange) entry;
687 /*! \brief set a member's status based on device state of that member's state_interface.
689 * Lock interface list find sc, iterate through each queues queue_member list for member to
690 * update state inside queues
692 static int update_status(const char *interface, const int status)
695 struct ao2_iterator mem_iter, queue_iter;
696 struct call_queue *q;
698 queue_iter = ao2_iterator_init(queues, 0);
699 while ((q = ao2_iterator_next(&queue_iter))) {
701 mem_iter = ao2_iterator_init(q->members, 0);
702 while ((cur = ao2_iterator_next(&mem_iter))) {
705 tmp_interface = ast_strdupa(cur->state_interface);
706 if ((slash_pos = strchr(interface, '/')))
707 if ((slash_pos = strchr(slash_pos + 1, '/')))
710 if (strcasecmp(interface, tmp_interface)) {
715 if (cur->status != status) {
716 cur->status = status;
717 if (q->maskmemberstatus) {
722 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
732 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime" : "static",
733 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
744 /*! \brief set a member's status based on device state of that member's interface*/
745 static int handle_statechange(void *datap)
747 struct member_interface *curint;
750 struct statechange *sc = datap;
752 technology = ast_strdupa(sc->dev);
753 loc = strchr(technology, '/');
761 AST_LIST_LOCK(&interfaces);
762 AST_LIST_TRAVERSE(&interfaces, curint, list) {
765 interface = ast_strdupa(curint->interface);
766 if ((slash_pos = strchr(interface, '/')))
767 if ((slash_pos = strchr(slash_pos + 1, '/')))
770 if (!strcasecmp(interface, sc->dev))
773 AST_LIST_UNLOCK(&interfaces);
776 if (option_debug > 2)
777 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state));
782 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
784 update_status(sc->dev, sc->state);
789 static void device_state_cb(const struct ast_event *event, void *unused)
791 enum ast_device_state state;
793 struct statechange *sc;
796 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
797 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
799 if (ast_strlen_zero(device)) {
800 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
803 datapsize = sizeof(*sc) + strlen(device) + 1;
804 if (!(sc = ast_calloc(1, datapsize))) {
805 ast_log(LOG_ERROR, "failed to calloc a state change struct\n");
809 strcpy(sc->dev, device);
810 if (ast_taskprocessor_push(devicestate_tps, handle_statechange, sc) < 0) {
815 /*! \brief allocate space for new queue member and set fields based on parameters passed */
816 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
820 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
821 cur->penalty = penalty;
822 cur->paused = paused;
823 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
824 if (!ast_strlen_zero(state_interface))
825 ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
827 ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
828 if (!ast_strlen_zero(membername))
829 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
831 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
832 if (!strchr(cur->interface, '/'))
833 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
834 cur->status = ast_device_state(cur->state_interface);
841 static int compress_char(const char c)
851 static int member_hash_fn(const void *obj, const int flags)
853 const struct member *mem = obj;
854 const char *chname = strchr(mem->interface, '/');
857 chname = mem->interface;
858 for (i = 0; i < 5 && chname[i]; i++)
859 ret += compress_char(chname[i]) << (i * 6);
863 static int member_cmp_fn(void *obj1, void *obj2, int flags)
865 struct member *mem1 = obj1, *mem2 = obj2;
866 return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH;
870 * \brief Initialize Queue default values.
871 * \note the queue's lock must be held before executing this function
873 static void init_queue(struct call_queue *q)
876 struct penalty_rule *pr_iter;
879 q->retry = DEFAULT_RETRY;
882 q->announcefrequency = 0;
883 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
884 q->announceholdtime = 1;
885 q->announcepositionlimit = 10; /* Default 10 positions */
886 q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
887 q->roundingseconds = 0; /* Default - don't announce seconds */
890 q->setinterfacevar = 0;
892 q->setqueueentryvar = 0;
893 q->autofill = autofill_default;
894 q->montype = montype_default;
896 q->reportholdtime = 0;
899 q->leavewhenempty = 0;
901 q->maskmemberstatus = 0;
902 q->eventwhencalled = 0;
904 q->timeoutrestart = 0;
905 q->periodicannouncefrequency = 0;
906 q->randomperiodicannounce = 0;
907 q->numperiodicannounce = 0;
909 if (q->strategy == QUEUE_STRATEGY_LINEAR)
910 /* linear strategy depends on order, so we have to place all members in a single bucket */
911 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
913 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
918 ast_string_field_set(q, sound_next, "queue-youarenext");
919 ast_string_field_set(q, sound_thereare, "queue-thereare");
920 ast_string_field_set(q, sound_calls, "queue-callswaiting");
921 ast_string_field_set(q, queue_quantity1, "queue-quantity1");
922 ast_string_field_set(q, queue_quantity2, "queue-quantity2");
923 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
924 ast_string_field_set(q, sound_minutes, "queue-minutes");
925 ast_string_field_set(q, sound_minute, "queue-minute");
926 ast_string_field_set(q, sound_seconds, "queue-seconds");
927 ast_string_field_set(q, sound_thanks, "queue-thankyou");
928 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
930 if ((q->sound_periodicannounce[0] = ast_str_create(32)))
931 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
933 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
934 if (q->sound_periodicannounce[i])
935 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
938 while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list)))
942 static void clear_queue(struct call_queue *q)
945 q->callscompleted = 0;
946 q->callsabandoned = 0;
947 q->callscompletedinsl = 0;
951 static int add_to_interfaces(const char *interface)
953 struct member_interface *curint;
955 AST_LIST_LOCK(&interfaces);
956 AST_LIST_TRAVERSE(&interfaces, curint, list) {
957 if (!strcasecmp(curint->interface, interface))
962 AST_LIST_UNLOCK(&interfaces);
966 ast_debug(1, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
968 if ((curint = ast_calloc(1, sizeof(*curint)))) {
969 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
970 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
972 AST_LIST_UNLOCK(&interfaces);
977 static int interface_exists_global(const char *interface)
979 struct call_queue *q;
980 struct member *mem, tmpmem;
981 struct ao2_iterator queue_iter, mem_iter;
984 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
985 queue_iter = ao2_iterator_init(queues, 0);
986 while ((q = ao2_iterator_next(&queue_iter))) {
988 mem_iter = ao2_iterator_init(q->members, 0);
989 while ((mem = ao2_iterator_next(&mem_iter))) {
990 if (!strcasecmp(mem->state_interface, interface)) {
1003 static int remove_from_interfaces(const char *interface)
1005 struct member_interface *curint;
1007 if (interface_exists_global(interface))
1010 AST_LIST_LOCK(&interfaces);
1011 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
1012 if (!strcasecmp(curint->interface, interface)) {
1013 ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
1014 AST_LIST_REMOVE_CURRENT(list);
1019 AST_LIST_TRAVERSE_SAFE_END;
1020 AST_LIST_UNLOCK(&interfaces);
1025 static void clear_and_free_interfaces(void)
1027 struct member_interface *curint;
1029 AST_LIST_LOCK(&interfaces);
1030 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
1032 AST_LIST_UNLOCK(&interfaces);
1036 * \brief Change queue penalty by adding rule.
1038 * Check rule for errors with time or fomatting, see if rule is relative to rest
1039 * of queue, iterate list of rules to find correct insertion point, insert and return.
1040 * \retval -1 on failure
1041 * \retval 0 on success
1042 * \note Call this with the rule_lists locked
1044 static int insert_penaltychange (const char *list_name, const char *content, const int linenum)
1046 char *timestr, *maxstr, *minstr, *contentdup;
1047 struct penalty_rule *rule = NULL, *rule_iter;
1048 struct rule_list *rl_iter;
1049 int time, inserted = 0;
1051 if (!(rule = ast_calloc(1, sizeof(*rule)))) {
1052 ast_log(LOG_ERROR, "Cannot allocate memory for penaltychange rule at line %d!\n", linenum);
1056 contentdup = ast_strdupa(content);
1058 if (!(maxstr = strchr(contentdup, ','))) {
1059 ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
1065 timestr = contentdup;
1067 if ((time = atoi(timestr)) < 0) {
1068 ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
1075 if ((minstr = strchr(maxstr,',')))
1078 /* The last check will evaluate true if either no penalty change is indicated for a given rule
1079 * OR if a min penalty change is indicated but no max penalty change is */
1080 if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
1081 rule->max_relative = 1;
1084 rule->max_value = atoi(maxstr);
1086 if (!ast_strlen_zero(minstr)) {
1087 if (*minstr == '+' || *minstr == '-')
1088 rule->min_relative = 1;
1089 rule->min_value = atoi(minstr);
1090 } else /*there was no minimum specified, so assume this means no change*/
1091 rule->min_relative = 1;
1093 /*We have the rule made, now we need to insert it where it belongs*/
1094 AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
1095 if (strcasecmp(rl_iter->name, list_name))
1098 AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
1099 if (rule->time < rule_iter->time) {
1100 AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
1105 AST_LIST_TRAVERSE_SAFE_END;
1108 AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
1115 /*! \brief Configure a queue parameter.
1117 * The failunknown flag is set for config files (and static realtime) to show
1118 * errors for unknown parameters. It is cleared for dynamic realtime to allow
1119 * extra fields in the tables.
1120 * \note For error reporting, line number is passed for .conf static configuration,
1121 * for Realtime queues, linenum is -1.
1123 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
1125 if (!strcasecmp(param, "musicclass") ||
1126 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
1127 ast_string_field_set(q, moh, val);
1128 } else if (!strcasecmp(param, "announce")) {
1129 ast_string_field_set(q, announce, val);
1130 } else if (!strcasecmp(param, "context")) {
1131 ast_string_field_set(q, context, val);
1132 } else if (!strcasecmp(param, "timeout")) {
1133 q->timeout = atoi(val);
1135 q->timeout = DEFAULT_TIMEOUT;
1136 } else if (!strcasecmp(param, "ringinuse")) {
1137 q->ringinuse = ast_true(val);
1138 } else if (!strcasecmp(param, "setinterfacevar")) {
1139 q->setinterfacevar = ast_true(val);
1140 } else if (!strcasecmp(param, "setqueuevar")) {
1141 q->setqueuevar = ast_true(val);
1142 } else if (!strcasecmp(param, "setqueueentryvar")) {
1143 q->setqueueentryvar = ast_true(val);
1144 } else if (!strcasecmp(param, "monitor-format")) {
1145 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
1146 } else if (!strcasecmp(param, "membermacro")) {
1147 ast_string_field_set(q, membermacro, val);
1148 } else if (!strcasecmp(param, "membergosub")) {
1149 ast_string_field_set(q, membergosub, val);
1150 } else if (!strcasecmp(param, "queue-youarenext")) {
1151 ast_string_field_set(q, sound_next, val);
1152 } else if (!strcasecmp(param, "queue-thereare")) {
1153 ast_string_field_set(q, sound_thereare, val);
1154 } else if (!strcasecmp(param, "queue-callswaiting")) {
1155 ast_string_field_set(q, sound_calls, val);
1156 } else if (!strcasecmp(param, "queue-quantity1")) {
1157 ast_string_field_set(q, queue_quantity1, val);
1158 } else if (!strcasecmp(param, "queue-quantity2")) {
1159 ast_string_field_set(q, queue_quantity2, val);
1160 } else if (!strcasecmp(param, "queue-holdtime")) {
1161 ast_string_field_set(q, sound_holdtime, val);
1162 } else if (!strcasecmp(param, "queue-minutes")) {
1163 ast_string_field_set(q, sound_minutes, val);
1164 } else if (!strcasecmp(param, "queue-minute")) {
1165 ast_string_field_set(q, sound_minute, val);
1166 } else if (!strcasecmp(param, "queue-seconds")) {
1167 ast_string_field_set(q, sound_seconds, val);
1168 } else if (!strcasecmp(param, "queue-thankyou")) {
1169 ast_string_field_set(q, sound_thanks, val);
1170 } else if (!strcasecmp(param, "queue-callerannounce")) {
1171 ast_string_field_set(q, sound_callerannounce, val);
1172 } else if (!strcasecmp(param, "queue-reporthold")) {
1173 ast_string_field_set(q, sound_reporthold, val);
1174 } else if (!strcasecmp(param, "announce-frequency")) {
1175 q->announcefrequency = atoi(val);
1176 } else if (!strcasecmp(param, "min-announce-frequency")) {
1177 q->minannouncefrequency = atoi(val);
1178 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
1179 } else if (!strcasecmp(param, "announce-round-seconds")) {
1180 q->roundingseconds = atoi(val);
1181 /* Rounding to any other values just doesn't make sense... */
1182 if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
1183 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
1185 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1186 "using 0 instead for queue '%s' at line %d of queues.conf\n",
1187 val, param, q->name, linenum);
1189 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1190 "using 0 instead for queue '%s'\n", val, param, q->name);
1192 q->roundingseconds=0;
1194 } else if (!strcasecmp(param, "announce-holdtime")) {
1195 if (!strcasecmp(val, "once"))
1196 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1197 else if (ast_true(val))
1198 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1200 q->announceholdtime = 0;
1201 } else if (!strcasecmp(param, "announce-position")) {
1202 if (!strcasecmp(val, "limit"))
1203 q->announceposition = ANNOUNCEPOSITION_LIMIT;
1204 else if (!strcasecmp(val, "more"))
1205 q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
1206 else if (ast_true(val))
1207 q->announceposition = ANNOUNCEPOSITION_YES;
1209 q->announceposition = ANNOUNCEPOSITION_NO;
1210 } else if (!strcasecmp(param, "announce-position-limit")) {
1211 q->announcepositionlimit = atoi(val);
1212 } else if (!strcasecmp(param, "periodic-announce")) {
1213 if (strchr(val, ',')) {
1214 char *s, *buf = ast_strdupa(val);
1217 while ((s = strsep(&buf, ",|"))) {
1218 if (!q->sound_periodicannounce[i])
1219 q->sound_periodicannounce[i] = ast_str_create(16);
1220 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
1222 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
1225 q->numperiodicannounce = i;
1227 ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
1228 q->numperiodicannounce = 1;
1230 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
1231 q->periodicannouncefrequency = atoi(val);
1232 } else if (!strcasecmp(param, "random-periodic-announce")) {
1233 q->randomperiodicannounce = ast_true(val);
1234 } else if (!strcasecmp(param, "retry")) {
1235 q->retry = atoi(val);
1237 q->retry = DEFAULT_RETRY;
1238 } else if (!strcasecmp(param, "wrapuptime")) {
1239 q->wrapuptime = atoi(val);
1240 } else if (!strcasecmp(param, "autofill")) {
1241 q->autofill = ast_true(val);
1242 } else if (!strcasecmp(param, "monitor-type")) {
1243 if (!strcasecmp(val, "mixmonitor"))
1245 } else if (!strcasecmp(param, "autopause")) {
1246 q->autopause = ast_true(val);
1247 } else if (!strcasecmp(param, "maxlen")) {
1248 q->maxlen = atoi(val);
1251 } else if (!strcasecmp(param, "servicelevel")) {
1252 q->servicelevel= atoi(val);
1253 } else if (!strcasecmp(param, "strategy")) {
1254 /* We already have set this, no need to do it again */
1256 } else if (!strcasecmp(param, "joinempty")) {
1257 if (!strcasecmp(val, "loose"))
1258 q->joinempty = QUEUE_EMPTY_LOOSE;
1259 else if (!strcasecmp(val, "strict"))
1260 q->joinempty = QUEUE_EMPTY_STRICT;
1261 else if (ast_true(val))
1262 q->joinempty = QUEUE_EMPTY_NORMAL;
1265 } else if (!strcasecmp(param, "leavewhenempty")) {
1266 if (!strcasecmp(val, "loose"))
1267 q->leavewhenempty = QUEUE_EMPTY_LOOSE;
1268 else if (!strcasecmp(val, "strict"))
1269 q->leavewhenempty = QUEUE_EMPTY_STRICT;
1270 else if (ast_true(val))
1271 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
1273 q->leavewhenempty = 0;
1274 } else if (!strcasecmp(param, "eventmemberstatus")) {
1275 q->maskmemberstatus = !ast_true(val);
1276 } else if (!strcasecmp(param, "eventwhencalled")) {
1277 if (!strcasecmp(val, "vars")) {
1278 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
1280 q->eventwhencalled = ast_true(val) ? 1 : 0;
1282 } else if (!strcasecmp(param, "reportholdtime")) {
1283 q->reportholdtime = ast_true(val);
1284 } else if (!strcasecmp(param, "memberdelay")) {
1285 q->memberdelay = atoi(val);
1286 } else if (!strcasecmp(param, "weight")) {
1287 q->weight = atoi(val);
1290 /* With Realtime queues, if the last queue using weights is deleted in realtime,
1291 we will not see any effect on use_weight until next reload. */
1292 } else if (!strcasecmp(param, "timeoutrestart")) {
1293 q->timeoutrestart = ast_true(val);
1294 } else if (!strcasecmp(param, "defaultrule")) {
1295 ast_string_field_set(q, defaultrule, val);
1296 } else if (failunknown) {
1298 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
1299 q->name, param, linenum);
1301 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
1307 * \brief Find rt member record to update otherwise create one.
1309 * Search for member in queue, if found update penalty/paused state,
1310 * if no memeber exists create one flag it as a RT member and add to queue member list.
1312 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface)
1314 struct member *m, tmpmem;
1319 penalty = atoi(penalty_str);
1325 paused = atoi(paused_str);
1330 /* Find the member, or the place to put a new one. */
1331 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
1332 m = ao2_find(q->members, &tmpmem, OBJ_POINTER);
1334 /* Create a new one if not found, else update penalty */
1336 if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
1339 add_to_interfaces(m->state_interface);
1340 ao2_link(q->members, m);
1346 m->dead = 0; /* Do not delete this one. */
1349 if (strcasecmp(state_interface, m->state_interface)) {
1350 remove_from_interfaces(m->state_interface);
1351 ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
1352 add_to_interfaces(m->state_interface);
1354 m->penalty = penalty;
1359 /*! \brief Iterate through queue's member list and delete them */
1360 static void free_members(struct call_queue *q, int all)
1362 /* Free non-dynamic members */
1364 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1366 while ((cur = ao2_iterator_next(&mem_iter))) {
1367 if (all || !cur->dynamic) {
1368 ao2_unlink(q->members, cur);
1369 remove_from_interfaces(cur->state_interface);
1376 /*! \brief Free queue's member list then its string fields */
1377 static void destroy_queue(void *obj)
1379 struct call_queue *q = obj;
1383 ast_string_field_free_memory(q);
1384 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1385 if (q->sound_periodicannounce[i])
1386 free(q->sound_periodicannounce[i]);
1388 ao2_ref(q->members, -1);
1391 static struct call_queue *alloc_queue(const char *queuename)
1393 struct call_queue *q;
1395 if ((q = ao2_alloc(sizeof(*q), destroy_queue))) {
1396 if (ast_string_field_init(q, 64)) {
1400 ast_string_field_set(q, name, queuename);
1406 * \brief Reload a single queue via realtime.
1408 * Check for statically defined queue first, check if deleted RT queue,
1409 * check for new RT queue, if queue vars are not defined init them with defaults.
1410 * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
1411 * \retval the queue,
1412 * \retval NULL if it doesn't exist.
1413 * \note Should be called with the "queues" container locked.
1415 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
1417 struct ast_variable *v;
1418 struct call_queue *q, tmpq = {
1422 struct ao2_iterator mem_iter;
1423 char *interface = NULL;
1424 const char *tmp_name;
1426 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
1428 /* Static queues override realtime. */
1429 if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) {
1437 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
1443 } else if (!member_config)
1444 /* Not found in the list, and it's not realtime ... */
1447 /* Check if queue is defined in realtime. */
1449 /* Delete queue from in-core list if it has been deleted in realtime. */
1451 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1452 found condition... So we might delete an in-core queue
1453 in case of DB failure. */
1454 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
1457 /* Delete if unused (else will be deleted when last caller leaves). */
1458 ao2_unlink(queues, q);
1465 /* Create a new queue if an in-core entry does not exist yet. */
1467 struct ast_variable *tmpvar = NULL;
1468 if (!(q = alloc_queue(queuename)))
1473 /*Before we initialize the queue, we need to set the strategy, so that linear strategy
1474 * will allocate the members properly
1476 for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
1477 if (!strcasecmp(tmpvar->name, "strategy")) {
1478 q->strategy = strat2int(tmpvar->value);
1479 if (q->strategy < 0) {
1480 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
1481 tmpvar->value, q->name);
1482 q->strategy = QUEUE_STRATEGY_RINGALL;
1487 /* We traversed all variables and didn't find a strategy */
1489 q->strategy = QUEUE_STRATEGY_RINGALL;
1490 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1491 ao2_link(queues, q);
1494 memset(tmpbuf, 0, sizeof(tmpbuf));
1495 for (v = queue_vars; v; v = v->next) {
1496 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1497 if ((tmp = strchr(v->name, '_'))) {
1498 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1501 while ((tmp = strchr(tmp, '_')))
1506 if (!ast_strlen_zero(v->value)) {
1507 /* Don't want to try to set the option if the value is empty */
1508 queue_set_param(q, tmp_name, v->value, -1, 0);
1512 /* Temporarily set realtime members dead so we can detect deleted ones.
1513 * Also set the membercount correctly for realtime*/
1514 mem_iter = ao2_iterator_init(q->members, 0);
1515 while ((m = ao2_iterator_next(&mem_iter))) {
1522 while ((interface = ast_category_browse(member_config, interface))) {
1523 rt_handle_member_record(q, interface,
1524 S_OR(ast_variable_retrieve(member_config, interface, "membername"),interface),
1525 ast_variable_retrieve(member_config, interface, "penalty"),
1526 ast_variable_retrieve(member_config, interface, "paused"),
1527 S_OR(ast_variable_retrieve(member_config, interface, "state_interface"),interface));
1530 /* Delete all realtime members that have been deleted in DB. */
1531 mem_iter = ao2_iterator_init(q->members, 0);
1532 while ((m = ao2_iterator_next(&mem_iter))) {
1534 ao2_unlink(q->members, m);
1535 remove_from_interfaces(m->state_interface);
1546 static struct call_queue *load_realtime_queue(const char *queuename)
1548 struct ast_variable *queue_vars;
1549 struct ast_config *member_config = NULL;
1550 struct call_queue *q = NULL, tmpq = {
1554 /* Find the queue in the in-core list first. */
1555 q = ao2_find(queues, &tmpq, OBJ_POINTER);
1557 if (!q || q->realtime) {
1558 /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
1559 queue operations while waiting for the DB.
1561 This will be two separate database transactions, so we might
1562 see queue parameters as they were before another process
1563 changed the queue and member list as it was after the change.
1564 Thus we might see an empty member list when a queue is
1565 deleted. In practise, this is unlikely to cause a problem. */
1567 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1569 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1570 if (!member_config) {
1571 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1572 ast_variables_destroy(queue_vars);
1578 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1580 ast_config_destroy(member_config);
1582 ast_variables_destroy(queue_vars);
1586 update_realtime_members(q);
1591 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
1593 struct ast_variable *var;
1596 if (!(var = ast_load_realtime("queue_members", "interface", mem->interface, "queue_name", queue_name, NULL)))
1599 if (!strcmp(var->name, "uniqueid"))
1603 if (var && !ast_strlen_zero(var->value)) {
1604 if ((ast_update_realtime("queue_members", "uniqueid", var->value, field, value, NULL)) > -1)
1610 static void update_realtime_members(struct call_queue *q)
1612 struct ast_config *member_config = NULL;
1614 char *interface = NULL;
1615 struct ao2_iterator mem_iter;
1617 if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , NULL))) {
1618 /*This queue doesn't have realtime members*/
1619 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
1625 /* Temporarily set realtime members dead so we can detect deleted ones.*/
1626 mem_iter = ao2_iterator_init(q->members, 0);
1627 while ((m = ao2_iterator_next(&mem_iter))) {
1633 while ((interface = ast_category_browse(member_config, interface))) {
1634 rt_handle_member_record(q, interface,
1635 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1636 ast_variable_retrieve(member_config, interface, "penalty"),
1637 ast_variable_retrieve(member_config, interface, "paused"),
1638 S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface));
1641 /* Delete all realtime members that have been deleted in DB. */
1642 mem_iter = ao2_iterator_init(q->members, 0);
1643 while ((m = ao2_iterator_next(&mem_iter))) {
1645 ao2_unlink(q->members, m);
1646 remove_from_interfaces(m->state_interface);
1652 ast_config_destroy(member_config);
1655 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1657 struct call_queue *q;
1658 struct queue_ent *cur, *prev = NULL;
1662 enum queue_member_status stat;
1664 if (!(q = load_realtime_queue(queuename)))
1670 /* This is our one */
1671 stat = get_member_status(q, qe->max_penalty, qe->min_penalty);
1672 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1673 *reason = QUEUE_JOINEMPTY;
1674 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
1675 *reason = QUEUE_JOINUNAVAIL;
1676 else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1677 *reason = QUEUE_JOINUNAVAIL;
1678 else if (q->maxlen && (q->count >= q->maxlen))
1679 *reason = QUEUE_FULL;
1681 /* There's space for us, put us at the right position inside
1683 * Take into account the priority of the calling user */
1688 /* We have higher priority than the current user, enter
1689 * before him, after all the other users with priority
1690 * higher or equal to our priority. */
1691 if ((!inserted) && (qe->prio > cur->prio)) {
1692 insert_entry(q, prev, qe, &pos);
1699 /* No luck, join at the end of the queue */
1701 insert_entry(q, prev, qe, &pos);
1702 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1703 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1704 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1707 manager_event(EVENT_FLAG_CALL, "Join",
1708 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1710 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1711 S_OR(qe->chan->cid.cid_name, "unknown"),
1712 q->name, qe->pos, q->count, qe->chan->uniqueid );
1713 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1721 static int play_file(struct ast_channel *chan, const char *filename)
1725 ast_stopstream(chan);
1727 res = ast_streamfile(chan, filename, chan->language);
1729 res = ast_waitstream(chan, AST_DIGIT_ANY);
1731 ast_stopstream(chan);
1737 * \brief Check for valid exit from queue via goto
1738 * \retval 0 if failure
1739 * \retval 1 if successful
1741 static int valid_exit(struct queue_ent *qe, char digit)
1743 int digitlen = strlen(qe->digits);
1745 /* Prevent possible buffer overflow */
1746 if (digitlen < sizeof(qe->digits) - 2) {
1747 qe->digits[digitlen] = digit;
1748 qe->digits[digitlen + 1] = '\0';
1750 qe->digits[0] = '\0';
1754 /* If there's no context to goto, short-circuit */
1755 if (ast_strlen_zero(qe->context))
1758 /* If the extension is bad, then reset the digits to blank */
1759 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1760 qe->digits[0] = '\0';
1764 /* We have an exact match */
1765 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1766 qe->valid_digits = 1;
1767 /* Return 1 on a successful goto */
1774 static int say_position(struct queue_ent *qe, int ringing)
1776 int res = 0, avgholdmins, avgholdsecs, announceposition = 0;
1779 /* Let minannouncefrequency seconds pass between the start of each position announcement */
1781 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
1784 /* If either our position has changed, or we are over the freq timer, say position */
1785 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1789 ast_indicate(qe->chan,-1);
1791 ast_moh_stop(qe->chan);
1794 if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
1795 qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
1796 (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
1797 qe->pos <= qe->parent->announcepositionlimit))
1798 announceposition = 1;
1801 if (announceposition == 1) {
1802 /* Say we're next, if we are */
1804 res = play_file(qe->chan, qe->parent->sound_next);
1810 if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
1812 res = play_file(qe->chan, qe->parent->queue_quantity1);
1815 res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
1820 res = play_file(qe->chan, qe->parent->sound_thereare);
1823 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
1827 if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
1829 res = play_file(qe->chan, qe->parent->queue_quantity2);
1833 res = play_file(qe->chan, qe->parent->sound_calls);
1839 /* Round hold time to nearest minute */
1840 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1842 /* If they have specified a rounding then round the seconds as well */
1843 if (qe->parent->roundingseconds) {
1844 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1845 avgholdsecs *= qe->parent->roundingseconds;
1850 ast_verb(3, "Hold time for %s is %d minute(s) %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1852 /* If the hold time is >1 min, if it's enabled, and if it's not
1853 supposed to be only once and we have already said it, say it */
1854 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1855 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1856 res = play_file(qe->chan, qe->parent->sound_holdtime);
1860 if (avgholdmins > 1) {
1861 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1865 if (avgholdmins == 1) {
1866 res = play_file(qe->chan, qe->parent->sound_minute);
1870 res = play_file(qe->chan, qe->parent->sound_minutes);
1875 if (avgholdsecs > 1) {
1876 res = ast_say_number(qe->chan, avgholdmins > 1 ? avgholdsecs : avgholdmins * 60 + avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1880 res = play_file(qe->chan, qe->parent->sound_seconds);
1888 if (announceposition == 1){
1889 if (qe->parent->announceposition) {
1890 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
1891 qe->chan->name, qe->parent->name, qe->pos);
1893 res = play_file(qe->chan, qe->parent->sound_thanks);
1896 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
1899 /* Set our last_pos indicators */
1901 qe->last_pos_said = qe->pos;
1903 /* Don't restart music on hold if we're about to exit the caller from the queue */
1906 ast_indicate(qe->chan, AST_CONTROL_RINGING);
1908 ast_moh_start(qe->chan, qe->moh, NULL);
1914 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
1918 /* Calculate holdtime using a recursive boxcar filter */
1919 /* Thanks to SRT for this contribution */
1920 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1922 ao2_lock(qe->parent);
1923 oldvalue = qe->parent->holdtime;
1924 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
1925 ao2_unlock(qe->parent);
1928 /*! \brief Caller leaving queue.
1930 * Search the queue to find the leaving client, if found remove from queue
1931 * create manager event, move others up the queue.
1933 static void leave_queue(struct queue_ent *qe)
1935 struct call_queue *q;
1936 struct queue_ent *cur, *prev = NULL;
1937 struct penalty_rule *pr_iter;
1940 if (!(q = qe->parent))
1946 for (cur = q->head; cur; cur = cur->next) {
1950 /* Take us out of the queue */
1951 manager_event(EVENT_FLAG_CALL, "Leave",
1952 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1953 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1954 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1955 /* Take us out of the queue */
1957 prev->next = cur->next;
1959 q->head = cur->next;
1960 /* Free penalty rules */
1961 while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list)))
1964 /* Renumber the people after us in the queue based on a new count */
1971 /*If the queue is a realtime queue, check to see if it's still defined in real time*/
1973 if (!ast_load_realtime("queues", "name", q->name, NULL))
1978 /* It's dead and nobody is in it, so kill it */
1979 ao2_unlink(queues, q);
1980 /* unref the container's reference to the queue */
1983 /* unref the explicit ref earlier in the function */
1987 /*! \brief Hang up a list of outgoing calls */
1988 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1990 struct callattempt *oo;
1993 /* Hangup any existing lines we have open */
1994 if (outgoing->chan && (outgoing->chan != exception))
1995 ast_hangup(outgoing->chan);
1997 outgoing = outgoing->q_next;
1999 ao2_ref(oo->member, -1);
2005 * \brief traverse all defined queues which have calls waiting and contain this member
2006 * \retval 0 if no other queue has precedence (higher weight)
2007 * \retval 1 if found
2009 static int compare_weight(struct call_queue *rq, struct member *member)
2011 struct call_queue *q;
2014 struct ao2_iterator queue_iter;
2016 /* q's lock and rq's lock already set by try_calling()
2017 * to solve deadlock */
2018 queue_iter = ao2_iterator_init(queues, 0);
2019 while ((q = ao2_iterator_next(&queue_iter))) {
2020 if (q == rq) { /* don't check myself, could deadlock */
2025 if (q->count && q->members) {
2026 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
2027 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
2028 if (q->weight > rq->weight) {
2029 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);
2045 /*! \brief common hangup actions */
2046 static void do_hang(struct callattempt *o)
2049 ast_hangup(o->chan);
2053 /*! \brief convert "\n" to "\nVariable: " ready for manager to use */
2054 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
2056 struct ast_str *buf = ast_str_alloca(len + 1);
2059 if (pbx_builtin_serialize_variables(chan, &buf)) {
2062 /* convert "\n" to "\nVariable: " */
2063 strcpy(vars, "Variable: ");
2066 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
2069 if (tmp[i + 1] == '\0')
2071 if (tmp[i] == '\n') {
2075 ast_copy_string(&(vars[j]), "Variable: ", len - j);
2085 /* there are no channel variables; leave it blank */
2092 * \brief Part 2 of ring_one
2094 * Does error checking before attempting to request a channel and call a member.
2095 * This function is only called from ring_one().
2096 * Failure can occur if:
2099 * - Wrapup time not expired
2100 * - Priority by another queue
2102 * \retval 1 on success to reach a free agent
2103 * \retval 0 on failure to get agent.
2105 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
2111 const char *macrocontext, *macroexten;
2113 /* on entry here, we know that tmp->chan == NULL */
2114 if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
2115 (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
2116 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
2117 (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
2119 ast_cdr_busy(qe->chan->cdr);
2120 tmp->stillgoing = 0;
2125 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
2126 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
2128 ast_cdr_busy(qe->chan->cdr);
2129 tmp->stillgoing = 0;
2133 if (tmp->member->paused) {
2134 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
2136 ast_cdr_busy(qe->chan->cdr);
2137 tmp->stillgoing = 0;
2140 if (use_weight && compare_weight(qe->parent,tmp->member)) {
2141 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
2143 ast_cdr_busy(qe->chan->cdr);
2144 tmp->stillgoing = 0;
2149 ast_copy_string(tech, tmp->interface, sizeof(tech));
2150 if ((location = strchr(tech, '/')))
2155 /* Request the peer */
2156 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
2157 if (!tmp->chan) { /* If we can't, just go on to the next call */
2159 ast_cdr_busy(qe->chan->cdr);
2160 tmp->stillgoing = 0;
2162 update_status(tmp->member->state_interface, ast_device_state(tmp->member->state_interface));
2164 ao2_lock(qe->parent);
2165 qe->parent->rrpos++;
2167 ao2_unlock(qe->parent);
2174 tmp->chan->appl = "AppQueue";
2175 tmp->chan->data = "(Outgoing Line)";
2176 memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
2177 if (tmp->chan->cid.cid_num)
2178 ast_free(tmp->chan->cid.cid_num);
2179 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
2180 if (tmp->chan->cid.cid_name)
2181 ast_free(tmp->chan->cid.cid_name);
2182 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
2183 if (tmp->chan->cid.cid_ani)
2184 ast_free(tmp->chan->cid.cid_ani);
2185 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
2187 /* Inherit specially named variables from parent channel */
2188 ast_channel_inherit_variables(qe->chan, tmp->chan);
2190 /* Presense of ADSI CPE on outgoing channel follows ours */
2191 tmp->chan->adsicpe = qe->chan->adsicpe;
2193 /* Inherit context and extension */
2194 ast_channel_lock(qe->chan);
2195 macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
2196 if (!ast_strlen_zero(macrocontext))
2197 ast_copy_string(tmp->chan->dialcontext, macrocontext, sizeof(tmp->chan->dialcontext));
2199 ast_copy_string(tmp->chan->dialcontext, qe->chan->context, sizeof(tmp->chan->dialcontext));
2200 macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
2201 if (!ast_strlen_zero(macroexten))
2202 ast_copy_string(tmp->chan->exten, macroexten, sizeof(tmp->chan->exten));
2204 ast_copy_string(tmp->chan->exten, qe->chan->exten, sizeof(tmp->chan->exten));
2205 ast_channel_unlock(qe->chan);
2207 /* Place the call, but don't wait on the answer */
2208 if ((res = ast_call(tmp->chan, location, 0))) {
2209 /* Again, keep going even if there's an error */
2210 ast_debug(1, "ast call on peer returned %d\n", res);
2211 ast_verb(3, "Couldn't call %s\n", tmp->interface);
2215 } else if (qe->parent->eventwhencalled) {
2218 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
2220 "AgentCalled: %s\r\n"
2222 "ChannelCalling: %s\r\n"
2223 "DestinationChannel: %s\r\n"
2224 "CallerIDNum: %s\r\n"
2225 "CallerIDName: %s\r\n"
2231 qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
2232 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
2233 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
2234 qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
2235 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2236 ast_verb(3, "Called %s\n", tmp->interface);
2242 /*! \brief find the entry with the best metric, or NULL */
2243 static struct callattempt *find_best(struct callattempt *outgoing)
2245 struct callattempt *best = NULL, *cur;
2247 for (cur = outgoing; cur; cur = cur->q_next) {
2248 if (cur->stillgoing && /* Not already done */
2249 !cur->chan && /* Isn't already going */
2250 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
2259 * \brief Place a call to a queue member.
2261 * Once metrics have been calculated for each member, this function is used
2262 * to place a call to the appropriate member (or members). The low-level
2263 * channel-handling and error detection is handled in ring_entry
2265 * \retval 1 if a member was called successfully
2266 * \retval 0 otherwise
2268 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
2273 struct callattempt *best = find_best(outgoing);
2275 ast_debug(1, "Nobody left to try ringing in queue\n");
2278 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2279 struct callattempt *cur;
2280 /* Ring everyone who shares this best metric (for ringall) */
2281 for (cur = outgoing; cur; cur = cur->q_next) {
2282 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
2283 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
2284 ret |= ring_entry(qe, cur, busies);
2288 /* Ring just the best channel */
2289 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
2290 ret = ring_entry(qe, best, busies);
2297 /*! \brief Search for best metric and add to Round Robbin queue */
2298 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
2300 struct callattempt *best = find_best(outgoing);
2303 /* Ring just the best channel */
2304 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2305 qe->parent->rrpos = best->metric % 1000;
2307 /* Just increment rrpos */
2308 if (qe->parent->wrapped) {
2309 /* No more channels, start over */
2310 qe->parent->rrpos = 0;
2312 /* Prioritize next entry */
2313 qe->parent->rrpos++;
2316 qe->parent->wrapped = 0;
2321 /*! \brief Search for best metric and add to Linear queue */
2322 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
2324 struct callattempt *best = find_best(outgoing);
2327 /* Ring just the best channel */
2328 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2329 qe->linpos = best->metric % 1000;
2331 /* Just increment rrpos */
2332 if (qe->linwrapped) {
2333 /* No more channels, start over */
2336 /* Prioritize next entry */
2345 /*! \brief Playback announcement to queued members if peroid has elapsed */
2346 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
2351 /* Get the current time */
2354 /* Check to see if it is time to announce */
2355 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
2358 /* Stop the music on hold so we can play our own file */
2360 ast_indicate(qe->chan,-1);
2362 ast_moh_stop(qe->chan);
2364 ast_verb(3, "Playing periodic announcement\n");
2366 if (qe->parent->randomperiodicannounce) {
2367 qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
2368 } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
2369 ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str)) {
2370 qe->last_periodic_announce_sound = 0;
2373 /* play the announcement */
2374 res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str);
2376 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
2379 /* Resume Music on Hold if the caller is going to stay in the queue */
2382 ast_indicate(qe->chan, AST_CONTROL_RINGING);
2384 ast_moh_start(qe->chan, qe->moh, NULL);
2387 /* update last_periodic_announce_time */
2388 qe->last_periodic_announce_time = now;
2390 /* Update the current periodic announcement to the next announcement */
2391 if (!qe->parent->randomperiodicannounce) {
2392 qe->last_periodic_announce_sound++;
2398 /*! \brief Record that a caller gave up on waiting in queue */
2399 static void record_abandoned(struct queue_ent *qe)
2401 ao2_lock(qe->parent);
2402 set_queue_variables(qe);
2403 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
2407 "OriginalPosition: %d\r\n"
2409 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
2411 qe->parent->callsabandoned++;
2412 ao2_unlock(qe->parent);
2415 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
2416 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
2418 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
2419 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
2420 if (qe->parent->autopause) {
2421 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
2422 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
2424 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
2430 #define AST_MAX_WATCHERS 256
2431 /*! \brief Wait for a member to answer the call
2433 * \param[in] qe the queue_ent corresponding to the caller in the queue
2434 * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
2435 * \param[in] to the amount of time (in milliseconds) to wait for a response
2436 * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
2437 * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
2438 * \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
2439 * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
2441 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
2443 const char *queue = qe->parent->name;
2444 struct callattempt *o, *start = NULL, *prev = NULL;
2446 int numbusies = prebusies;
2450 struct ast_frame *f;
2451 struct callattempt *peer = NULL;
2452 struct ast_channel *winner;
2453 struct ast_channel *in = qe->chan;
2455 char membername[80] = "";
2459 struct callattempt *epollo;
2462 starttime = (long) time(NULL);
2464 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2466 ast_poll_channel_add(in, epollo->chan);
2470 while (*to && !peer) {
2471 int numlines, retry, pos = 1;
2472 struct ast_channel *watchers[AST_MAX_WATCHERS];
2476 for (retry = 0; retry < 2; retry++) {
2478 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
2479 if (o->stillgoing) { /* Keep track of important channels */
2482 watchers[pos++] = o->chan;
2486 prev->call_next = o;
2492 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
2493 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
2495 /* On "ringall" strategy we only move to the next penalty level
2496 when *all* ringing phones are done in the current penalty level */
2497 ring_one(qe, outgoing, &numbusies);
2500 if (pos == 1 /* not found */) {
2501 if (numlines == (numbusies + numnochan)) {
2502 ast_debug(1, "Everyone is busy at this time\n");
2504 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
2509 winner = ast_waitfor_n(watchers, pos, to);
2510 for (o = start; o; o = o->call_next) {
2511 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
2513 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2516 } else if (o->chan && (o->chan == winner)) {
2518 ast_copy_string(on, o->member->interface, sizeof(on));
2519 ast_copy_string(membername, o->member->membername, sizeof(membername));
2521 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
2522 ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
2527 } else if (!ast_strlen_zero(o->chan->call_forward)) {
2532 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
2533 if ((stuff = strchr(tmpchan, '/'))) {
2537 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
2541 /* Before processing channel, go ahead and check for forwarding */
2542 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2543 /* Setup parameters */
2544 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2546 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
2550 ast_channel_inherit_variables(in, o->chan);
2551 ast_channel_datastore_inherit(in, o->chan);
2552 if (o->chan->cid.cid_num)
2553 ast_free(o->chan->cid.cid_num);
2554 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
2556 if (o->chan->cid.cid_name)
2557 ast_free(o->chan->cid.cid_name);
2558 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
2560 ast_string_field_set(o->chan, accountcode, in->accountcode);
2561 o->chan->cdrflags = in->cdrflags;
2563 if (in->cid.cid_ani) {
2564 if (o->chan->cid.cid_ani)
2565 ast_free(o->chan->cid.cid_ani);
2566 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
2568 if (o->chan->cid.cid_rdnis)
2569 ast_free(o->chan->cid.cid_rdnis);
2570 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
2571 if (ast_call(o->chan, tmpchan, 0)) {
2572 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
2577 /* Hangup the original channel now, in case we needed it */
2581 f = ast_read(winner);
2583 if (f->frametype == AST_FRAME_CONTROL) {
2584 switch (f->subclass) {
2585 case AST_CONTROL_ANSWER:
2586 /* This is our guy if someone answered. */
2588 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2592 case AST_CONTROL_BUSY:
2593 ast_verb(3, "%s is busy\n", o->chan->name);
2595 ast_cdr_busy(in->cdr);
2597 endtime = (long) time(NULL);
2598 endtime -= starttime;
2599 rna(endtime*1000, qe, on, membername);
2600 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2601 if (qe->parent->timeoutrestart)
2603 ring_one(qe, outgoing, &numbusies);
2607 case AST_CONTROL_CONGESTION:
2608 ast_verb(3, "%s is circuit-busy\n", o->chan->name);
2610 ast_cdr_busy(in->cdr);
2611 endtime = (long) time(NULL);
2612 endtime -= starttime;
2613 rna(endtime*1000, qe, on, membername);
2615 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2616 if (qe->parent->timeoutrestart)
2618 ring_one(qe, outgoing, &numbusies);
2622 case AST_CONTROL_RINGING:
2623 ast_verb(3, "%s is ringing\n", o->chan->name);
2625 case AST_CONTROL_OFFHOOK:
2626 /* Ignore going off hook */
2629 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
2634 endtime = (long) time(NULL) - starttime;
2635 rna(endtime * 1000, qe, on, membername);
2637 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2638 if (qe->parent->timeoutrestart)
2640 ring_one(qe, outgoing, &numbusies);
2647 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2652 in->hangupcause = f->seqno;
2657 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2658 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
2663 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass)) {
2664 ast_verb(3, "User pressed digit: %c\n", f->subclass);
2666 *digit = f->subclass;
2673 for (o = start; o; o = o->call_next)
2674 rna(orig, qe, o->interface, o->member->membername);
2679 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2681 ast_poll_channel_del(in, epollo->chan);
2689 * \brief Check if we should start attempting to call queue members.
2691 * The behavior of this function is dependent first on whether autofill is enabled
2692 * and second on whether the ring strategy is ringall. If autofill is not enabled,
2693 * then return true if we're the head of the queue. If autofill is enabled, then
2694 * we count the available members and see if the number of available members is enough
2695 * that given our position in the queue, we would theoretically be able to connect to
2696 * one of those available members
2698 static int is_our_turn(struct queue_ent *qe)
2700 struct queue_ent *ch;
2706 if (!qe->parent->autofill) {
2707 /* Atomically read the parent head -- does not need a lock */
2708 ch = qe->parent->head;
2709 /* If we are now at the top of the head, break out */
2711 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2714 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2719 /* This needs a lock. How many members are available to be served? */
2720 ao2_lock(qe->parent);
2722 ch = qe->parent->head;
2724 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2725 ast_debug(1, "Even though there may be multiple members available, the strategy is ringall so only the head call is allowed in\n");
2728 struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
2729 while ((cur = ao2_iterator_next(&mem_iter))) {
2730 switch (cur->status) {
2731 case AST_DEVICE_INUSE:
2732 if (!qe->parent->ringinuse)
2734 /* else fall through */
2735 case AST_DEVICE_NOT_INUSE:
2736 case AST_DEVICE_UNKNOWN:
2745 ast_debug(1, "There are %d available members.\n", avl);
2747 while ((idx < avl) && (ch) && (ch != qe)) {
2753 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2754 if (ch && idx < avl) {
2755 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2758 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2762 ao2_unlock(qe->parent);
2769 * \brief update rules for queues
2771 * Calculate min/max penalties making sure if relative they stay within bounds.
2772 * Update queues penalty and set dialplan vars, goto next list entry.
2774 static void update_qe_rule(struct queue_ent *qe)
2776 int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
2777 int min_penalty = qe->pr->min_relative ? qe->min_penalty + qe->pr->min_value : qe->pr->min_value;
2778 char max_penalty_str[20], min_penalty_str[20];
2779 /* a relative change to the penalty could put it below 0 */
2780 if (max_penalty < 0)
2782 if (min_penalty < 0)
2784 if (min_penalty > max_penalty)
2785 min_penalty = max_penalty;
2786 snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
2787 snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
2788 pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
2789 pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
2790 qe->max_penalty = max_penalty;
2791 qe->min_penalty = min_penalty;
2792 ast_debug(3, "Setting max penalty to %d and min penalty to %d for caller %s since %d seconds have elapsed\n", qe->max_penalty, qe->min_penalty, qe->chan->name, qe->pr->time);
2793 qe->pr = AST_LIST_NEXT(qe->pr, list);
2796 /*! \brief The waiting areas for callers who are not actively calling members
2798 * This function is one large loop. This function will return if a caller
2799 * either exits the queue or it becomes that caller's turn to attempt calling
2800 * queue members. Inside the loop, we service the caller with periodic announcements,
2801 * holdtime announcements, etc. as configured in queues.conf
2803 * \retval 0 if the caller's turn has arrived
2804 * \retval -1 if the caller should exit the queue.
2806 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2810 /* This is the holding pen for callers 2 through maxlen */
2812 enum queue_member_status stat;
2814 if (is_our_turn(qe))
2817 /* If we have timed out, break out */
2818 if (qe->expire && (time(NULL) > qe->expire)) {
2819 *reason = QUEUE_TIMEOUT;
2823 stat = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty);
2825 /* leave the queue if no agents, if enabled */
2826 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2827 *reason = QUEUE_LEAVEEMPTY;
2828 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2833 /* leave the queue if no reachable agents, if enabled */
2834 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
2835 *reason = QUEUE_LEAVEUNAVAIL;
2836 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2840 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2841 *reason = QUEUE_LEAVEUNAVAIL;
2842 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2847 /* Make a position announcement, if enabled */
2848 if (qe->parent->announcefrequency &&
2849 (res = say_position(qe,ringing)))
2852 /* Make a periodic announcement, if enabled */
2853 if (qe->parent->periodicannouncefrequency &&
2854 (res = say_periodic_announcement(qe,ringing)))
2857 /* see if we need to move to the next penalty level for this queue */
2858 while (qe->pr && ((time(NULL) - qe->start) > qe->pr->time)) {
2862 /* Wait a second before checking again */
2863 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
2864 if (res > 0 && !valid_exit(qe, res))
2875 * \brief update the queue status
2878 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl)
2881 struct call_queue *qtmp;
2882 struct ao2_iterator queue_iter;
2884 if (shared_lastcall) {
2885 queue_iter = ao2_iterator_init(queues, 0);
2886 while ((qtmp = ao2_iterator_next(&queue_iter))) {
2888 if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
2889 time(&mem->lastcall);
2899 time(&member->lastcall);
2901 member->lastqueue = q;
2905 q->callscompleted++;
2906 if (callcompletedinsl)
2907 q->callscompletedinsl++;
2912 /*! \brief Calculate the metric of each member in the outgoing callattempts
2914 * A numeric metric is given to each member depending on the ring strategy used
2915 * by the queue. Members with lower metrics will be called before members with
2917 * \retval -1 if penalties are exceeded
2918 * \retval 0 otherwise
2920 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2922 if ((qe->max_penalty && (mem->penalty > qe->max_penalty)) || (qe->min_penalty && (mem->penalty < qe->min_penalty)))
2925 switch (q->strategy) {
2926 case QUEUE_STRATEGY_RINGALL:
2927 /* Everyone equal, except for penalty */
2928 tmp->metric = mem->penalty * 1000000;
2930 case QUEUE_STRATEGY_LINEAR:
2931 if (pos < qe->linpos) {
2932 tmp->metric = 1000 + pos;
2934 if (pos > qe->linpos)
2935 /* Indicate there is another priority */
2939 tmp->metric += mem->penalty * 1000000;
2941 case QUEUE_STRATEGY_RRMEMORY:
2942 if (pos < q->rrpos) {
2943 tmp->metric = 1000 + pos;
2946 /* Indicate there is another priority */
2950 tmp->metric += mem->penalty * 1000000;
2952 case QUEUE_STRATEGY_RANDOM:
2953 tmp->metric = ast_random() % 1000;
2954 tmp->metric += mem->penalty * 1000000;
2956 case QUEUE_STRATEGY_WRANDOM:
2957 tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
2959 case QUEUE_STRATEGY_FEWESTCALLS:
2960 tmp->metric = mem->calls;
2961 tmp->metric += mem->penalty * 1000000;
2963 case QUEUE_STRATEGY_LEASTRECENT:
2967 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2968 tmp->metric += mem->penalty * 1000000;
2971 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2977 enum agent_complete_reason {
2983 /*! \brief Send out AMI message with member call completion status information */
2984 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
2985 const struct ast_channel *peer, const struct member *member, time_t callstart,
2986 char *vars, size_t vars_len, enum agent_complete_reason rsn)
2988 const char *reason = NULL; /* silence dumb compilers */
2990 if (!qe->parent->eventwhencalled)
3001 reason = "transfer";
3005 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
3010 "MemberName: %s\r\n"
3015 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
3016 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
3017 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
3020 /*! \brief A large function which calls members, updates statistics, and bridges the caller and a member
3022 * Here is the process of this function
3023 * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
3024 * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
3025 * iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
3026 * member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also
3027 * during each iteration, we call calc_metric to determine which members should be rung when.
3028 * 3. Call ring_one to place a call to the appropriate member(s)
3029 * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
3030 * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
3031 * 6. Start the monitor or mixmonitor if the option is set
3032 * 7. Remove the caller from the queue to allow other callers to advance
3033 * 8. Bridge the call.
3034 * 9. Do any post processing after the call has disconnected.
3036 * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
3037 * \param[in] options the options passed as the third parameter to the Queue() application
3038 * \param[in] announceoverride filename to play to user when waiting
3039 * \param[in] url the url passed as the fourth parameter to the Queue() application
3040 * \param[in,out] tries the number of times we have tried calling queue members
3041 * \param[out] noption set if the call to Queue() has the 'n' option set.
3042 * \param[in] agi the agi passed as the fifth parameter to the Queue() application
3043 * \param[in] macro the macro passed as the sixth parameter to the Queue() application
3044 * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
3045 * \param[in] ringing 1 if the 'r' option is set, otherwise 0
3047 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
3050 struct callattempt *outgoing = NULL; /* the list of calls we are building */
3052 char oldexten[AST_MAX_EXTENSION]="";
3053 char oldcontext[AST_MAX_CONTEXT]="";
3054 char queuename[256]="";
3055 char interfacevar[256]="";
3056 struct ast_channel *peer;
3057 struct ast_channel *which;
3058 struct callattempt *lpeer;
3059 struct member *member;
3060 struct ast_app *app;
3061 int res = 0, bridge = 0;
3064 char *announce = NULL;
3067 time_t now = time(NULL);
3068 struct ast_bridge_config bridge_config;
3069 char nondataquality = 1;
3070 char *agiexec = NULL;
3071 char *macroexec = NULL;
3072 char *gosubexec = NULL;
3074 const char *monitorfilename;
3075 const char *monitor_exec;
3076 const char *monitor_options;
3077 char tmpid[256], tmpid2[256];
3078 char meid[1024], meid2[1024];
3079 char mixmonargs[1512];
3080 struct ast_app *mixmonapp = NULL;
3083 int forwardsallowed = 1;
3084 int callcompletedinsl;
3085 struct ao2_iterator memi;
3086 struct ast_datastore *datastore;
3088 ast_channel_lock(qe->chan);
3089 datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
3090 ast_channel_unlock(qe->chan);
3092 memset(&bridge_config, 0, sizeof(bridge_config));
3097 for (; options && *options; options++)
3100 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
3103 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
3106 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
3109 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
3115 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
3118 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
3121 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
3124 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
3127 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR)
3130 *tries = qe->parent->membercount;
3134 forwardsallowed = 0;
3137 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
3140 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
3145 /* Hold the lock while we setup the outgoing calls */
3148 ao2_lock(qe->parent);
3149 ast_debug(1, "%s is trying to call a queue member.\n",
3151 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
3152 if (!ast_strlen_zero(qe->announce))
3153 announce = qe->announce;
3154 if (!ast_strlen_zero(announceoverride))
3155 announce = announceoverride;
3157 memi = ao2_iterator_init(qe->parent->members, 0);
3158 while ((cur = ao2_iterator_next(&memi))) {
3159 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
3160 struct ast_dialed_interface *di;
3161 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
3164 ao2_unlock(qe->parent);
3170 if (!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) {
3172 ao2_unlock(qe->parent);
3178 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3179 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
3181 ao2_unlock(&qe->parent);
3187 datastore->data = dialed_interfaces;
3188 AST_LIST_HEAD_INIT(dialed_interfaces);
3190 ast_channel_lock(qe->chan);
3191 ast_channel_datastore_add(qe->chan, datastore);
3192 ast_channel_unlock(qe->chan);
3194 dialed_interfaces = datastore->data;
3196 AST_LIST_LOCK(dialed_interfaces);
3197 AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
3198 if (!strcasecmp(cur->interface, di->interface)) {
3199 ast_log(LOG_DEBUG, "Skipping dialing interface '%s' since it has already been dialed\n",
3204 AST_LIST_UNLOCK(dialed_interfaces);
3211 /* It is always ok to dial a Local interface. We only keep track of
3212 * which "real" interfaces have been dialed. The Local channel will
3213 * inherit this list so that if it ends up dialing a real interface,
3214 * it won't call one that has already been called. */
3215 if (strncasecmp(cur->interface, "Local/", 6)) {
3216 if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
3218 ao2_unlock(qe->parent);
3224 strcpy(di->interface, cur->interface);
3226 AST_LIST_LOCK(dialed_interfaces);
3227 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
3228 AST_LIST_UNLOCK(dialed_interfaces);
3231 tmp->stillgoing = -1;
3233 tmp->oldstatus = cur->status;
3234 tmp->lastcall = cur->lastcall;
3235 tmp->lastqueue = cur->lastqueue;
3236 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
3237 /* Special case: If we ring everyone, go ahead and ring them, otherwise
3238 just calculate their metric for the appropriate strategy */
3239 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
3240 /* Put them in the list of outgoing thingies... We're ready now.
3241 XXX If we're forcibly removed, these outgoing calls won't get
3243 tmp->q_next = outgoing;
3245 /* If this line is up, don't try anybody else */
3246 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
3253 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
3254 to = (qe->expire - now) * 1000;
3256 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
3259 ao2_unlock(qe->parent);
3260 ring_one(qe, outgoing, &numbusies);
3263 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
3264 /* The ast_channel_datastore_remove() function could fail here if the
3265 * datastore was moved to another channel during a masquerade. If this is
3266 * the case, don't free the datastore here because later, when the channel
3267 * to which the datastore was moved hangs up, it will attempt to free this
3268 * datastore again, causing a crash
3270 if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
3271 ast_channel_datastore_free(datastore);
3273 ao2_lock(qe->parent);
3274 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
3275 store_next_rr(qe, outgoing);
3277 if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
3278 store_next_lin(qe, outgoing);
3280 ao2_unlock(qe->parent);
3281 peer = lpeer ? lpeer->chan : NULL;
3285 /* Must gotten hung up */
3288 /* User exited by pressing a digit */
3292 ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
3293 } else { /* peer is valid */
3294 /* Ah ha! Someone answered within the desired timeframe. Of course after this
3295 we will always return with -1 so that it is hung up properly after the
3298 if (!strcmp(qe->chan->tech->type, "Zap"))
3299 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
3300 if (!strcmp(peer->tech->type, "Zap"))
3301 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
3302 /* Update parameters for the queue */
3304 recalc_holdtime(qe, (now - qe->start));
3305 ao2_lock(qe->parent);
3306 callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
3307 ao2_unlock(qe->parent);
3308 member = lpeer->member;
3309 /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
3311 hangupcalls(outgoing, peer);
3313 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
3316 res2 = ast_autoservice_start(qe->chan);
3318 if (qe->parent->memberdelay) {
3319 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
3320 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
3322 if (!res2 && announce) {
3323 play_file(peer, announce);
3325 if (!res2 && qe->parent->reportholdtime) {
3326 if (!play_file(peer, qe->parent->sound_reporthold)) {
3327 int holdtime, holdtimesecs;
3330 holdtime = abs((now - qe->start) / 60);
3331 holdtimesecs = abs((now - qe->start));
3332 if (holdtime == 1) {
3333 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
3334 play_file(peer, qe->parent->sound_minute);
3336 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
3337 play_file(peer, qe->parent->sound_minutes);
3339 if (holdtimesecs > 1) {
3340 ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, peer->language, NULL);
3341 play_file(peer, qe->parent->sound_seconds);
3346 res2 |= ast_autoservice_stop(qe->chan);
3347 if (ast_check_hangup(peer)) {
3348 /* Agent must have hung up */
3349 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
3350 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
3351 record_abandoned(qe);
3352 if (qe->parent->eventwhencalled)
3353 manager_event(EVENT_FLAG_AGENT, "AgentDump",
3358 "MemberName: %s\r\n"
3360 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
3361 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3363 ao2_ref(member, -1);
3366 /* Caller must have hung up just before being connected*/
3367 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
3368 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
3369 record_abandoned(qe);
3371 ao2_ref(member, -1);
3375 /* Stop music on hold */
3377 ast_indicate(qe->chan,-1);
3379 ast_moh_stop(qe->chan);
3380 /* If appropriate, log that we have a destination channel */
3382 ast_cdr_setdestchan(qe->chan->cdr, peer->name);
3383 /* Make sure channels are compatible */
3384 res = ast_channel_make_compatible(qe->chan, peer);
3386 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
3387 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
3388 record_abandoned(qe);
3390 ao2_ref(member, -1);