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"
97 QUEUE_STRATEGY_RINGALL = 0,
98 QUEUE_STRATEGY_LEASTRECENT,
99 QUEUE_STRATEGY_FEWESTCALLS,
100 QUEUE_STRATEGY_RANDOM,
101 QUEUE_STRATEGY_RRMEMORY,
102 QUEUE_STRATEGY_LINEAR,
103 QUEUE_STRATEGY_WRANDOM
106 static struct strategy {
110 { QUEUE_STRATEGY_RINGALL, "ringall" },
111 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
112 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
113 { QUEUE_STRATEGY_RANDOM, "random" },
114 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
115 { QUEUE_STRATEGY_LINEAR, "linear" },
116 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
119 #define DEFAULT_RETRY 5
120 #define DEFAULT_TIMEOUT 15
121 #define RECHECK 1 /* Recheck every second to see we we're at the top yet */
122 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
123 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /* The minimum number of seconds between position announcements
124 The default value of 15 provides backwards compatibility */
125 #define MAX_QUEUE_BUCKETS 53
127 #define RES_OKAY 0 /* Action completed */
128 #define RES_EXISTS (-1) /* Entry already exists */
129 #define RES_OUTOFMEMORY (-2) /* Out of memory */
130 #define RES_NOSUCHQUEUE (-3) /* No such queue */
131 #define RES_NOT_DYNAMIC (-4) /* Member is not dynamic */
133 static char *app = "Queue";
135 static char *synopsis = "Queue a call for a call queue";
137 static char *descrip =
138 " Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub][,rule]):\n"
139 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
140 "This application will return to the dialplan if the queue does not exist, or\n"
141 "any of the join options cause the caller to not enter the queue.\n"
142 "The option string may contain zero or more of the following characters:\n"
143 " 'c' -- continue in the dialplan if the callee hangs up.\n"
144 " 'd' -- data-quality (modem) call (minimum delay).\n"
145 " 'h' -- allow callee to hang up by pressing *.\n"
146 " 'H' -- allow caller to hang up by pressing *.\n"
147 " 'n' -- no retries on the timeout; will exit this application and \n"
148 " go to the next step.\n"
149 " 'i' -- ignore call forward requests from queue members and do nothing\n"
150 " when they are requested.\n"
151 " 'r' -- ring instead of playing MOH. Periodic Announcements are still made, if applicable.\n"
152 " 't' -- allow the called user to transfer the calling user.\n"
153 " 'T' -- allow the calling user to transfer the call.\n"
154 " 'w' -- allow the called user to write the conversation to disk via Monitor.\n"
155 " 'W' -- allow the calling user to write the conversation to disk via Monitor.\n"
156 " 'k' -- Allow the called party to enable parking of the call by sending\n"
157 " the DTMF sequence defined for call parking in features.conf.\n"
158 " 'K' -- Allow the calling party to enable parking of the call by sending\n"
159 " the DTMF sequence defined for call parking in features.conf.\n"
160 " 'x' -- allow the called user to write the conversation to disk via MixMonitor\n"
161 " 'X' -- allow the calling user to write the conversation to disk via MixMonitor\n"
163 " In addition to transferring the call, a call may be parked and then picked\n"
164 "up by another user.\n"
165 " The optional URL will be sent to the called party if the channel supports\n"
167 " The optional AGI parameter will setup an AGI script to be executed on the \n"
168 "calling party's channel once they are connected to a queue member.\n"
169 " The optional macro parameter will run a macro on the \n"
170 "calling party's channel once they are connected to a queue member.\n"
171 " The optional gosub parameter will run a gosub on the \n"
172 "calling party's channel once they are connected to a queue member.\n"
173 " The optional rule parameter will cause the queue's defaultrule to be\n"
174 "overridden by the rule specified.\n"
175 " The timeout will cause the queue to fail out after a specified number of\n"
176 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
177 " This application sets the following channel variable upon completion:\n"
178 " QUEUESTATUS The status of the call as a text string, one of\n"
179 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\n";
181 static char *app_aqm = "AddQueueMember" ;
182 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
183 static char *app_aqm_descrip =
184 " AddQueueMember(queuename[,interface[,penalty[,options[,membername]]]]):\n"
185 "Dynamically adds interface to an existing queue.\n"
186 "If the interface is already in the queue it will return an error.\n"
187 " This application sets the following channel variable upon completion:\n"
188 " AQMSTATUS The status of the attempt to add a queue member as a \n"
189 " text string, one of\n"
190 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
191 "Example: AddQueueMember(techsupport,SIP/3000)\n"
194 static char *app_rqm = "RemoveQueueMember" ;
195 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
196 static char *app_rqm_descrip =
197 " RemoveQueueMember(queuename[,interface[,options]]):\n"
198 "Dynamically removes interface to an existing queue\n"
199 "If the interface is NOT in the queue it will return an error.\n"
200 " This application sets the following channel variable upon completion:\n"
201 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
202 " text string, one of\n"
203 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
204 "Example: RemoveQueueMember(techsupport,SIP/3000)\n"
207 static char *app_pqm = "PauseQueueMember" ;
208 static char *app_pqm_synopsis = "Pauses a queue member" ;
209 static char *app_pqm_descrip =
210 " PauseQueueMember([queuename],interface[,options[,reason]]):\n"
211 "Pauses (blocks calls for) a queue member.\n"
212 "The given interface will be paused in the given queue. This prevents\n"
213 "any calls from being sent from the queue to the interface until it is\n"
214 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
215 "queuename is given, the interface is paused in every queue it is a\n"
216 "member of. The application will fail if the interface is not found.\n"
217 "The reason string is entirely optional and is used to add extra information\n"
218 "to the appropriate queue_log entries and manager events.\n"
219 " This application sets the following channel variable upon completion:\n"
220 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
221 " text string, one of\n"
222 " PAUSED | NOTFOUND\n"
223 "Example: PauseQueueMember(,SIP/3000)\n";
225 static char *app_upqm = "UnpauseQueueMember" ;
226 static char *app_upqm_synopsis = "Unpauses a queue member" ;
227 static char *app_upqm_descrip =
228 " UnpauseQueueMember([queuename],interface[,options[,reason]]):\n"
229 "Unpauses (resumes calls to) a queue member.\n"
230 "This is the counterpart to PauseQueueMember and operates exactly the\n"
231 "same way, except it unpauses instead of pausing the given interface.\n"
232 "The reason string is entirely optional and is used to add extra information\n"
233 "to the appropriate queue_log entries and manager events.\n"
234 " This application sets the following channel variable upon completion:\n"
235 " UPQMSTATUS The status of the attempt to unpause a queue \n"
236 " member as a text string, one of\n"
237 " UNPAUSED | NOTFOUND\n"
238 "Example: UnpauseQueueMember(,SIP/3000)\n";
240 static char *app_ql = "QueueLog" ;
241 static char *app_ql_synopsis = "Writes to the queue_log" ;
242 static char *app_ql_descrip =
243 " QueueLog(queuename,uniqueid,agent,event[,additionalinfo]):\n"
244 "Allows you to write your own events into the queue log\n"
245 "Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)\n";
247 /*! \brief Persistent Members astdb family */
248 static const char *pm_family = "Queue/PersistentMembers";
249 /* The maximum length of each persistent member queue database entry */
250 #define PM_MAX_LEN 8192
252 /*! \brief queues.conf [general] option */
253 static int queue_keep_stats = 0;
255 /*! \brief queues.conf [general] option */
256 static int queue_persistent_members = 0;
258 /*! \brief queues.conf per-queue weight option */
259 static int use_weight = 0;
261 /*! \brief queues.conf [general] option */
262 static int autofill_default = 0;
264 /*! \brief queues.conf [general] option */
265 static int montype_default = 0;
267 /*! \brief queues.conf [general] option */
268 static int shared_lastcall = 0;
270 /*! \brief Subscription to device state change events */
271 static struct ast_event_sub *device_state_sub;
273 /*! \brief queues.conf [general] option */
274 static int update_cdr = 0;
280 QUEUE_LEAVEEMPTY = 3,
281 QUEUE_JOINUNAVAIL = 4,
282 QUEUE_LEAVEUNAVAIL = 5,
288 enum queue_result id;
290 } queue_results[] = {
291 { QUEUE_UNKNOWN, "UNKNOWN" },
292 { QUEUE_TIMEOUT, "TIMEOUT" },
293 { QUEUE_JOINEMPTY,"JOINEMPTY" },
294 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
295 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
296 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
297 { QUEUE_FULL, "FULL" },
298 { QUEUE_CONTINUE, "CONTINUE" },
301 /*! \brief We define a custom "local user" structure because we
302 use it not only for keeping track of what is in use but
303 also for keeping track of who we're dialing.
305 There are two "links" defined in this structure, q_next and call_next.
306 q_next links ALL defined callattempt structures into a linked list. call_next is
307 a link which allows for a subset of the callattempts to be traversed. This subset
308 is used in wait_for_answer so that irrelevant callattempts are not traversed. This
309 also is helpful so that queue logs are always accurate in the case where a call to
310 a member times out, especially if using the ringall strategy. */
313 struct callattempt *q_next;
314 struct callattempt *call_next;
315 struct ast_channel *chan;
321 struct call_queue *lastqueue;
322 struct member *member;
327 struct call_queue *parent; /*!< What queue is our parent */
328 char moh[80]; /*!< Name of musiconhold to be used */
329 char announce[80]; /*!< Announcement to play for member when call is answered */
330 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
331 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
332 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
333 int pos; /*!< Where we are in the queue */
334 int prio; /*!< Our priority */
335 int last_pos_said; /*!< Last position we told the user */
336 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
337 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
338 time_t last_pos; /*!< Last time we told the user their position */
339 int opos; /*!< Where we started in the queue */
340 int handled; /*!< Whether our call was handled */
341 int pending; /*!< Non-zero if we are attempting to call a member */
342 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
343 int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
344 int linpos; /*!< If using linear strategy, what position are we at? */
345 int linwrapped; /*!< Is the linpos wrapped? */
346 time_t start; /*!< When we started holding */
347 time_t expire; /*!< When this entry should expire (time out of queue) */
348 struct ast_channel *chan; /*!< Our channel */
349 AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
350 struct penalty_rule *pr; /*!< Pointer to the next penalty rule to implement */
351 struct queue_ent *next; /*!< The next queue entry */
355 char interface[80]; /*!< Technology/Location to dial to reach this member*/
356 char state_interface[80]; /*!< Technology/Location from which to read devicestate changes */
357 char membername[80]; /*!< Member name to use in queue logs */
358 int penalty; /*!< Are we a last resort? */
359 int calls; /*!< Number of calls serviced by this member */
360 int dynamic; /*!< Are we dynamically added? */
361 int realtime; /*!< Is this member realtime? */
362 int status; /*!< Status of queue member */
363 int paused; /*!< Are we paused (not accepting calls)? */
364 time_t lastcall; /*!< When last successful call was hungup */
365 struct call_queue *lastqueue; /*!< Last queue we received a call */
366 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
367 unsigned int delme:1; /*!< Flag to delete entry on reload */
370 struct member_interface {
372 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
375 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
377 /* values used in multi-bit flags in call_queue */
378 #define QUEUE_EMPTY_NORMAL 1
379 #define QUEUE_EMPTY_STRICT 2
380 #define QUEUE_EMPTY_LOOSE 3
381 #define ANNOUNCEHOLDTIME_ALWAYS 1
382 #define ANNOUNCEHOLDTIME_ONCE 2
383 #define QUEUE_EVENT_VARIABLES 3
385 struct penalty_rule {
386 int time; /*!< Number of seconds that need to pass before applying this rule */
387 int max_value; /*!< The amount specified in the penalty rule for max penalty */
388 int min_value; /*!< The amount specified in the penalty rule for min penalty */
389 int max_relative; /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
390 int min_relative; /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
391 AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */
395 AST_DECLARE_STRING_FIELDS(
397 AST_STRING_FIELD(name);
398 /*! Music on Hold class */
399 AST_STRING_FIELD(moh);
400 /*! Announcement to play when call is answered */
401 AST_STRING_FIELD(announce);
403 AST_STRING_FIELD(context);
404 /*! Macro to run upon member connection */
405 AST_STRING_FIELD(membermacro);
406 /*! Gosub to run upon member connection */
407 AST_STRING_FIELD(membergosub);
408 /*! Default rule to use if none specified in call to Queue() */
409 AST_STRING_FIELD(defaultrule);
410 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
411 AST_STRING_FIELD(sound_next);
412 /*! Sound file: "There are currently" (def. queue-thereare) */
413 AST_STRING_FIELD(sound_thereare);
414 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
415 AST_STRING_FIELD(sound_calls);
416 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
417 AST_STRING_FIELD(sound_holdtime);
418 /*! Sound file: "minutes." (def. queue-minutes) */
419 AST_STRING_FIELD(sound_minutes);
420 /*! Sound file: "less-than" (def. queue-lessthan) */
421 AST_STRING_FIELD(sound_lessthan);
422 /*! Sound file: "seconds." (def. queue-seconds) */
423 AST_STRING_FIELD(sound_seconds);
424 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
425 AST_STRING_FIELD(sound_thanks);
426 /*! Sound file: Custom announce for caller, no default */
427 AST_STRING_FIELD(sound_callerannounce);
428 /*! Sound file: "Hold time" (def. queue-reporthold) */
429 AST_STRING_FIELD(sound_reporthold);
431 /*! Sound files: Custom announce, no default */
432 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
434 unsigned int joinempty:2;
435 unsigned int eventwhencalled:2;
436 unsigned int leavewhenempty:2;
437 unsigned int ringinuse:1;
438 unsigned int setinterfacevar:1;
439 unsigned int setqueuevar:1;
440 unsigned int setqueueentryvar:1;
441 unsigned int reportholdtime:1;
442 unsigned int wrapped:1;
443 unsigned int timeoutrestart:1;
444 unsigned int announceholdtime:2;
445 unsigned int announceposition:1;
447 unsigned int maskmemberstatus:1;
448 unsigned int realtime:1;
449 unsigned int found:1;
450 int announcefrequency; /*!< How often to announce their position */
451 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
452 int periodicannouncefrequency; /*!< How often to play periodic announcement */
453 int roundingseconds; /*!< How many seconds do we round to? */
454 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
455 int callscompleted; /*!< Number of queue calls completed */
456 int callsabandoned; /*!< Number of queue calls abandoned */
457 int servicelevel; /*!< seconds setting for servicelevel*/
458 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
459 char monfmt[8]; /*!< Format to use when recording calls */
460 int montype; /*!< Monitor type Monitor vs. MixMonitor */
461 int count; /*!< How many entries */
462 int maxlen; /*!< Max number of entries */
463 int wrapuptime; /*!< Wrapup Time */
465 int retry; /*!< Retry calling everyone after this amount of time */
466 int timeout; /*!< How long to wait for an answer */
467 int weight; /*!< Respective weight */
468 int autopause; /*!< Auto pause queue members if they fail to answer */
470 /* Queue strategy things */
471 int rrpos; /*!< Round Robin - position */
472 int memberdelay; /*!< Seconds to delay connecting member to caller */
473 int autofill; /*!< Ignore the head call status and ring an available agent */
475 struct ao2_container *members; /*!< Head of the list of members */
477 * \brief Number of members _logged in_
478 * \note There will be members in the members container that are not logged
479 * in, so this can not simply be replaced with ao2_container_count().
482 struct queue_ent *head; /*!< Head of the list of callers */
483 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
484 AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
489 AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
490 AST_LIST_ENTRY(rule_list) list;
493 AST_LIST_HEAD_STATIC(rule_lists, rule_list);
495 static struct ao2_container *queues;
497 static void update_realtime_members(struct call_queue *q);
498 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
500 /*! \brief sets the QUEUESTATUS channel variable */
501 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
505 for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
506 if (queue_results[i].id == res) {
507 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
513 static char *int2strat(int strategy)
517 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
518 if (strategy == strategies[x].strategy)
519 return strategies[x].name;
525 static int strat2int(const char *strategy)
529 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
530 if (!strcasecmp(strategy, strategies[x].name))
531 return strategies[x].strategy;
537 static int queue_hash_cb(const void *obj, const int flags)
539 const struct call_queue *q = obj;
540 return ast_str_hash(q->name);
543 static int queue_cmp_cb(void *obj, void *arg, int flags)
545 struct call_queue *q = obj, *q2 = arg;
546 return !strcasecmp(q->name, q2->name) ? CMP_MATCH : 0;
549 static inline struct call_queue *queue_ref(struct call_queue *q)
555 static inline struct call_queue *queue_unref(struct call_queue *q)
561 static void set_queue_variables(struct queue_ent *qe)
564 char interfacevar[256]="";
567 if (qe->parent->setqueuevar) {
569 if (qe->parent->callscompleted > 0)
570 sl = 100 * ((float) qe->parent->callscompletedinsl / (float) qe->parent->callscompleted);
572 snprintf(interfacevar,sizeof(interfacevar),
573 "QUEUENAME=%s|QUEUEMAX=%d|QUEUESTRATEGY=%s|QUEUECALLS=%d|QUEUEHOLDTIME=%d|QUEUECOMPLETED=%d|QUEUEABANDONED=%d|QUEUESRVLEVEL=%d|QUEUESRVLEVELPERF=%2.1f",
574 qe->parent->name, qe->parent->maxlen, int2strat(qe->parent->strategy), qe->parent->count, qe->parent->holdtime, qe->parent->callscompleted,
575 qe->parent->callsabandoned, qe->parent->servicelevel, sl);
577 pbx_builtin_setvar(qe->chan, interfacevar);
581 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
582 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
584 struct queue_ent *cur;
601 enum queue_member_status {
603 QUEUE_NO_REACHABLE_MEMBERS,
604 QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
608 /*! \brief Check if members are available
610 * This function checks to see if members are available to be called. If any member
611 * is available, the function immediately returns QUEUE_NORMAL. If no members are available,
612 * the appropriate reason why is returned
614 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty, int min_penalty)
616 struct member *member;
617 struct ao2_iterator mem_iter;
618 enum queue_member_status result = QUEUE_NO_MEMBERS;
621 mem_iter = ao2_iterator_init(q->members, 0);
622 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
623 if ((max_penalty && (member->penalty > max_penalty)) || (min_penalty && (member->penalty < min_penalty)))
626 switch (member->status) {
627 case AST_DEVICE_INVALID:
630 case AST_DEVICE_UNAVAILABLE:
631 if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)
632 result = QUEUE_NO_REACHABLE_MEMBERS;
635 if (member->paused) {
636 result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
651 AST_LIST_ENTRY(statechange) entry;
655 /*! \brief set a member's status based on device state of that member's state_interface*/
656 static void *handle_statechange(struct statechange *sc)
658 struct call_queue *q;
660 struct ao2_iterator mem_iter;
661 struct member_interface *curint;
662 struct ao2_iterator queue_iter;
666 technology = ast_strdupa(sc->dev);
667 loc = strchr(technology, '/');
674 AST_LIST_LOCK(&interfaces);
675 AST_LIST_TRAVERSE(&interfaces, curint, list) {
678 interface = ast_strdupa(curint->interface);
679 if ((slash_pos = strchr(interface, '/')))
680 if ((slash_pos = strchr(slash_pos + 1, '/')))
683 if (!strcasecmp(interface, sc->dev))
686 AST_LIST_UNLOCK(&interfaces);
689 ast_debug(3, "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));
693 ast_debug(1, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
694 queue_iter = ao2_iterator_init(queues, 0);
695 while ((q = ao2_iterator_next(&queue_iter))) {
697 mem_iter = ao2_iterator_init(q->members, 0);
698 while ((cur = ao2_iterator_next(&mem_iter))) {
701 interface = ast_strdupa(cur->state_interface);
702 if ((slash_pos = strchr(interface, '/')))
703 if ((slash_pos = strchr(slash_pos + 1, '/')))
706 if (strcasecmp(sc->dev, interface)) {
711 if (cur->status != sc->state) {
712 cur->status = sc->state;
713 if (q->maskmemberstatus) {
718 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
728 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime" : "static",
729 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
741 * \brief Data used by the device state thread
744 /*! Set to 1 to stop the thread */
746 /*! The device state monitoring thread */
748 /*! Lock for the state change queue */
750 /*! Condition for the state change queue */
752 /*! Queue of state changes */
753 AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
755 .thread = AST_PTHREADT_NULL,
758 /*! \brief Consumer of the statechange queue */
759 static void *device_state_thread(void *data)
761 struct statechange *sc = NULL;
763 while (!device_state.stop) {
764 ast_mutex_lock(&device_state.lock);
765 if (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
766 ast_cond_wait(&device_state.cond, &device_state.lock);
767 sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry);
769 ast_mutex_unlock(&device_state.lock);
771 /* Check to see if we were woken up to see the request to stop */
772 if (device_state.stop)
778 handle_statechange(sc);
787 while ((sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry)))
792 /*! \brief Producer of the statechange queue */
793 static int statechange_queue(const char *dev, enum ast_device_state state)
795 struct statechange *sc;
797 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
801 strcpy(sc->dev, dev);
803 ast_mutex_lock(&device_state.lock);
804 AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
805 ast_cond_signal(&device_state.cond);
806 ast_mutex_unlock(&device_state.lock);
810 static void device_state_cb(const struct ast_event *event, void *unused)
812 enum ast_device_state state;
815 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
816 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
818 if (ast_strlen_zero(device)) {
819 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
823 statechange_queue(device, state);
826 /*! \brief allocate space for new queue member and set fields based on parameters passed */
827 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
831 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
832 cur->penalty = penalty;
833 cur->paused = paused;
834 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
835 if (!ast_strlen_zero(state_interface))
836 ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
838 ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
839 if (!ast_strlen_zero(membername))
840 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
842 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
843 if (!strchr(cur->interface, '/'))
844 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
845 cur->status = ast_device_state(cur->state_interface);
852 static int compress_char(const char c)
862 static int member_hash_fn(const void *obj, const int flags)
864 const struct member *mem = obj;
865 const char *chname = strchr(mem->interface, '/');
868 chname = mem->interface;
869 for (i = 0; i < 5 && chname[i]; i++)
870 ret += compress_char(chname[i]) << (i * 6);
874 static int member_cmp_fn(void *obj1, void *obj2, int flags)
876 struct member *mem1 = obj1, *mem2 = obj2;
877 return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH;
880 static void init_queue(struct call_queue *q)
883 struct penalty_rule *pr_iter;
886 q->retry = DEFAULT_RETRY;
889 q->announcefrequency = 0;
890 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
891 q->announceholdtime = 0;
892 q->announceholdtime = 1;
893 q->roundingseconds = 0; /* Default - don't announce seconds */
896 q->setinterfacevar = 0;
898 q->setqueueentryvar = 0;
899 q->autofill = autofill_default;
900 q->montype = montype_default;
902 q->reportholdtime = 0;
906 q->leavewhenempty = 0;
908 q->maskmemberstatus = 0;
909 q->eventwhencalled = 0;
911 q->timeoutrestart = 0;
912 q->periodicannouncefrequency = 0;
914 if (q->strategy == QUEUE_STRATEGY_LINEAR)
915 /* linear strategy depends on order, so we have to place all members in a single bucket */
916 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
918 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
923 ast_string_field_set(q, sound_next, "queue-youarenext");
924 ast_string_field_set(q, sound_thereare, "queue-thereare");
925 ast_string_field_set(q, sound_calls, "queue-callswaiting");
926 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
927 ast_string_field_set(q, sound_minutes, "queue-minutes");
928 ast_string_field_set(q, sound_seconds, "queue-seconds");
929 ast_string_field_set(q, sound_thanks, "queue-thankyou");
930 ast_string_field_set(q, sound_lessthan, "queue-less-than");
931 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
933 if ((q->sound_periodicannounce[0] = ast_str_create(32)))
934 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
936 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
937 if (q->sound_periodicannounce[i])
938 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
941 while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list)))
945 static void clear_queue(struct call_queue *q)
948 q->callscompleted = 0;
949 q->callsabandoned = 0;
950 q->callscompletedinsl = 0;
954 static int add_to_interfaces(const char *interface)
956 struct member_interface *curint;
958 AST_LIST_LOCK(&interfaces);
959 AST_LIST_TRAVERSE(&interfaces, curint, list) {
960 if (!strcasecmp(curint->interface, interface))
965 AST_LIST_UNLOCK(&interfaces);
969 ast_debug(1, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
971 if ((curint = ast_calloc(1, sizeof(*curint)))) {
972 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
973 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
975 AST_LIST_UNLOCK(&interfaces);
980 static int interface_exists_global(const char *interface)
982 struct call_queue *q;
983 struct member *mem, tmpmem;
984 struct ao2_iterator queue_iter, mem_iter;
987 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
988 queue_iter = ao2_iterator_init(queues, 0);
989 while ((q = ao2_iterator_next(&queue_iter))) {
991 mem_iter = ao2_iterator_init(q->members, 0);
992 while ((mem = ao2_iterator_next(&mem_iter))) {
993 if (!strcasecmp(mem->state_interface, interface)) {
1006 static int remove_from_interfaces(const char *interface)
1008 struct member_interface *curint;
1010 AST_LIST_LOCK(&interfaces);
1011 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
1012 if (!strcasecmp(curint->interface, interface)) {
1013 if (!interface_exists_global(interface)) {
1014 ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
1015 AST_LIST_REMOVE_CURRENT(list);
1021 AST_LIST_TRAVERSE_SAFE_END;
1022 AST_LIST_UNLOCK(&interfaces);
1027 static void clear_and_free_interfaces(void)
1029 struct member_interface *curint;
1031 AST_LIST_LOCK(&interfaces);
1032 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
1034 AST_LIST_UNLOCK(&interfaces);
1037 /*Note: call this with the rule_lists locked */
1038 static int insert_penaltychange (const char *list_name, const char *content, const int linenum)
1040 char *timestr, *maxstr, *minstr, *contentdup;
1041 struct penalty_rule *rule = NULL, *rule_iter;
1042 struct rule_list *rl_iter;
1043 int time, inserted = 0;
1045 if (!(rule = ast_calloc(1, sizeof(*rule)))) {
1046 ast_log(LOG_ERROR, "Cannot allocate memory for penaltychange rule at line %d!\n", linenum);
1050 contentdup = ast_strdupa(content);
1052 if (!(maxstr = strchr(contentdup, ','))) {
1053 ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
1059 timestr = contentdup;
1061 if ((time = atoi(timestr)) < 0) {
1062 ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
1069 if ((minstr = strchr(maxstr,',')))
1072 /* The last check will evaluate true if either no penalty change is indicated for a given rule
1073 * OR if a min penalty change is indicated but no max penalty change is */
1074 if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
1075 rule->max_relative = 1;
1078 rule->max_value = atoi(maxstr);
1080 if (!ast_strlen_zero(minstr)) {
1081 if (*minstr == '+' || *minstr == '-')
1082 rule->min_relative = 1;
1083 rule->min_value = atoi(minstr);
1084 } else /*there was no minimum specified, so assume this means no change*/
1085 rule->min_relative = 1;
1087 /*We have the rule made, now we need to insert it where it belongs*/
1088 AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
1089 if (strcasecmp(rl_iter->name, list_name))
1092 AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
1093 if (rule->time < rule_iter->time) {
1094 AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
1099 AST_LIST_TRAVERSE_SAFE_END;
1102 AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
1109 /*! \brief Configure a queue parameter.
1111 For error reporting, line number is passed for .conf static configuration.
1112 For Realtime queues, linenum is -1.
1113 The failunknown flag is set for config files (and static realtime) to show
1114 errors for unknown parameters. It is cleared for dynamic realtime to allow
1115 extra fields in the tables. */
1116 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
1118 if (!strcasecmp(param, "musicclass") ||
1119 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
1120 ast_string_field_set(q, moh, val);
1121 } else if (!strcasecmp(param, "announce")) {
1122 ast_string_field_set(q, announce, val);
1123 } else if (!strcasecmp(param, "context")) {
1124 ast_string_field_set(q, context, val);
1125 } else if (!strcasecmp(param, "timeout")) {
1126 q->timeout = atoi(val);
1128 q->timeout = DEFAULT_TIMEOUT;
1129 } else if (!strcasecmp(param, "ringinuse")) {
1130 q->ringinuse = ast_true(val);
1131 } else if (!strcasecmp(param, "setinterfacevar")) {
1132 q->setinterfacevar = ast_true(val);
1133 } else if (!strcasecmp(param, "setqueuevar")) {
1134 q->setqueuevar = ast_true(val);
1135 } else if (!strcasecmp(param, "setqueueentryvar")) {
1136 q->setqueueentryvar = ast_true(val);
1137 } else if (!strcasecmp(param, "monitor-format")) {
1138 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
1139 } else if (!strcasecmp(param, "membermacro")) {
1140 ast_string_field_set(q, membermacro, val);
1141 } else if (!strcasecmp(param, "membergosub")) {
1142 ast_string_field_set(q, membergosub, val);
1143 } else if (!strcasecmp(param, "queue-youarenext")) {
1144 ast_string_field_set(q, sound_next, val);
1145 } else if (!strcasecmp(param, "queue-thereare")) {
1146 ast_string_field_set(q, sound_thereare, val);
1147 } else if (!strcasecmp(param, "queue-callswaiting")) {
1148 ast_string_field_set(q, sound_calls, val);
1149 } else if (!strcasecmp(param, "queue-holdtime")) {
1150 ast_string_field_set(q, sound_holdtime, val);
1151 } else if (!strcasecmp(param, "queue-minutes")) {
1152 ast_string_field_set(q, sound_minutes, val);
1153 } else if (!strcasecmp(param, "queue-seconds")) {
1154 ast_string_field_set(q, sound_seconds, val);
1155 } else if (!strcasecmp(param, "queue-lessthan")) {
1156 ast_string_field_set(q, sound_lessthan, val);
1157 } else if (!strcasecmp(param, "queue-thankyou")) {
1158 ast_string_field_set(q, sound_thanks, val);
1159 } else if (!strcasecmp(param, "queue-callerannounce")) {
1160 ast_string_field_set(q, sound_callerannounce, val);
1161 } else if (!strcasecmp(param, "queue-reporthold")) {
1162 ast_string_field_set(q, sound_reporthold, val);
1163 } else if (!strcasecmp(param, "announce-frequency")) {
1164 q->announcefrequency = atoi(val);
1165 } else if (!strcasecmp(param, "min-announce-frequency")) {
1166 q->minannouncefrequency = atoi(val);
1167 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
1168 } else if (!strcasecmp(param, "announce-round-seconds")) {
1169 q->roundingseconds = atoi(val);
1170 /* Rounding to any other values just doesn't make sense... */
1171 if (!(q->roundingseconds == 0 || q->roundingseconds == 1 || q->roundingseconds == 5 || q->roundingseconds == 10
1172 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
1174 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1175 "using 0 instead for queue '%s' at line %d of queues.conf\n",
1176 val, param, q->name, linenum);
1178 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1179 "using 0 instead for queue '%s'\n", val, param, q->name);
1181 q->roundingseconds=0;
1183 } else if (!strcasecmp(param, "announce-holdtime")) {
1184 if (!strcasecmp(val, "once"))
1185 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1186 else if (ast_true(val))
1187 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1189 q->announceholdtime = 0;
1190 } else if (!strcasecmp(param, "announce-position")) {
1191 q->announceposition = ast_true(val);
1192 } else if (!strcasecmp(param, "periodic-announce")) {
1193 if (strchr(val, ',')) {
1194 char *s, *buf = ast_strdupa(val);
1197 while ((s = strsep(&buf, ",|"))) {
1198 if (!q->sound_periodicannounce[i])
1199 q->sound_periodicannounce[i] = ast_str_create(16);
1200 ast_str_set(&q->sound_periodicannounce[i], 0, s);
1202 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
1206 ast_str_set(&q->sound_periodicannounce[0], 0, val);
1208 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
1209 q->periodicannouncefrequency = atoi(val);
1210 } else if (!strcasecmp(param, "retry")) {
1211 q->retry = atoi(val);
1213 q->retry = DEFAULT_RETRY;
1214 } else if (!strcasecmp(param, "wrapuptime")) {
1215 q->wrapuptime = atoi(val);
1216 } else if (!strcasecmp(param, "autofill")) {
1217 q->autofill = ast_true(val);
1218 } else if (!strcasecmp(param, "monitor-type")) {
1219 if (!strcasecmp(val, "mixmonitor"))
1221 } else if (!strcasecmp(param, "autopause")) {
1222 q->autopause = ast_true(val);
1223 } else if (!strcasecmp(param, "maxlen")) {
1224 q->maxlen = atoi(val);
1227 } else if (!strcasecmp(param, "servicelevel")) {
1228 q->servicelevel= atoi(val);
1229 } else if (!strcasecmp(param, "strategy")) {
1230 /* We already have set this, no need to do it again */
1232 } else if (!strcasecmp(param, "joinempty")) {
1233 if (!strcasecmp(val, "loose"))
1234 q->joinempty = QUEUE_EMPTY_LOOSE;
1235 else if (!strcasecmp(val, "strict"))
1236 q->joinempty = QUEUE_EMPTY_STRICT;
1237 else if (ast_true(val))
1238 q->joinempty = QUEUE_EMPTY_NORMAL;
1241 } else if (!strcasecmp(param, "leavewhenempty")) {
1242 if (!strcasecmp(val, "loose"))
1243 q->leavewhenempty = QUEUE_EMPTY_LOOSE;
1244 else if (!strcasecmp(val, "strict"))
1245 q->leavewhenempty = QUEUE_EMPTY_STRICT;
1246 else if (ast_true(val))
1247 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
1249 q->leavewhenempty = 0;
1250 } else if (!strcasecmp(param, "eventmemberstatus")) {
1251 q->maskmemberstatus = !ast_true(val);
1252 } else if (!strcasecmp(param, "eventwhencalled")) {
1253 if (!strcasecmp(val, "vars")) {
1254 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
1256 q->eventwhencalled = ast_true(val) ? 1 : 0;
1258 } else if (!strcasecmp(param, "reportholdtime")) {
1259 q->reportholdtime = ast_true(val);
1260 } else if (!strcasecmp(param, "memberdelay")) {
1261 q->memberdelay = atoi(val);
1262 } else if (!strcasecmp(param, "weight")) {
1263 q->weight = atoi(val);
1266 /* With Realtime queues, if the last queue using weights is deleted in realtime,
1267 we will not see any effect on use_weight until next reload. */
1268 } else if (!strcasecmp(param, "timeoutrestart")) {
1269 q->timeoutrestart = ast_true(val);
1270 } else if (!strcasecmp(param, "defaultrule")) {
1271 ast_string_field_set(q, defaultrule, val);
1272 } else if (failunknown) {
1274 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
1275 q->name, param, linenum);
1277 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
1282 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)
1284 struct member *m, tmpmem;
1289 penalty = atoi(penalty_str);
1295 paused = atoi(paused_str);
1300 /* Find the member, or the place to put a new one. */
1301 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
1302 m = ao2_find(q->members, &tmpmem, OBJ_POINTER);
1304 /* Create a new one if not found, else update penalty */
1306 if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
1309 add_to_interfaces(m->state_interface);
1310 ao2_link(q->members, m);
1316 m->dead = 0; /* Do not delete this one. */
1319 if (strcasecmp(state_interface, m->state_interface)) {
1320 remove_from_interfaces(m->state_interface);
1321 ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
1322 add_to_interfaces(m->state_interface);
1324 m->penalty = penalty;
1329 static void free_members(struct call_queue *q, int all)
1331 /* Free non-dynamic members */
1333 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1335 while ((cur = ao2_iterator_next(&mem_iter))) {
1336 if (all || !cur->dynamic) {
1337 ao2_unlink(q->members, cur);
1338 remove_from_interfaces(cur->state_interface);
1345 static void destroy_queue(void *obj)
1347 struct call_queue *q = obj;
1350 ast_debug(0, "Queue destructor called for queue '%s'!\n", q->name);
1353 ast_string_field_free_memory(q);
1354 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1355 if (q->sound_periodicannounce[i])
1356 free(q->sound_periodicannounce[i]);
1358 ao2_ref(q->members, -1);
1361 static struct call_queue *alloc_queue(const char *queuename)
1363 struct call_queue *q;
1365 if ((q = ao2_alloc(sizeof(*q), destroy_queue))) {
1366 if (ast_string_field_init(q, 64)) {
1370 ast_string_field_set(q, name, queuename);
1375 /*!\brief Reload a single queue via realtime.
1376 \return Return the queue, or NULL if it doesn't exist.
1377 \note Should be called with the global qlock locked. */
1378 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
1380 struct ast_variable *v;
1381 struct call_queue *q, tmpq = {
1385 struct ao2_iterator mem_iter;
1386 char *interface = NULL;
1387 const char *tmp_name;
1389 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
1391 /* Static queues override realtime. */
1392 if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) {
1400 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
1406 } else if (!member_config)
1407 /* Not found in the list, and it's not realtime ... */
1410 /* Check if queue is defined in realtime. */
1412 /* Delete queue from in-core list if it has been deleted in realtime. */
1414 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1415 found condition... So we might delete an in-core queue
1416 in case of DB failure. */
1417 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
1420 /* Delete if unused (else will be deleted when last caller leaves). */
1421 ao2_unlink(queues, q);
1428 /* Create a new queue if an in-core entry does not exist yet. */
1430 struct ast_variable *tmpvar = NULL;
1431 if (!(q = alloc_queue(queuename)))
1436 /*Before we initialize the queue, we need to set the strategy, so that linear strategy
1437 * will allocate the members properly
1439 for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
1440 if (!strcasecmp(tmpvar->name, "strategy")) {
1441 q->strategy = strat2int(tmpvar->value);
1442 if (q->strategy < 0) {
1443 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
1444 tmpvar->value, q->name);
1445 q->strategy = QUEUE_STRATEGY_RINGALL;
1450 /* We traversed all variables and didn't find a strategy */
1452 q->strategy = QUEUE_STRATEGY_RINGALL;
1453 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1454 ao2_link(queues, q);
1455 ast_variables_destroy(tmpvar);
1458 memset(tmpbuf, 0, sizeof(tmpbuf));
1459 for (v = queue_vars; v; v = v->next) {
1460 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1461 if ((tmp = strchr(v->name, '_'))) {
1462 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1465 while ((tmp = strchr(tmp, '_')))
1469 queue_set_param(q, tmp_name, v->value, -1, 0);
1472 /* Temporarily set realtime members dead so we can detect deleted ones.
1473 * Also set the membercount correctly for realtime*/
1474 mem_iter = ao2_iterator_init(q->members, 0);
1475 while ((m = ao2_iterator_next(&mem_iter))) {
1482 while ((interface = ast_category_browse(member_config, interface))) {
1483 rt_handle_member_record(q, interface,
1484 S_OR(ast_variable_retrieve(member_config, interface, "membername"),interface),
1485 ast_variable_retrieve(member_config, interface, "penalty"),
1486 ast_variable_retrieve(member_config, interface, "paused"),
1487 S_OR(ast_variable_retrieve(member_config, interface, "state_interface"),interface));
1490 /* Delete all realtime members that have been deleted in DB. */
1491 mem_iter = ao2_iterator_init(q->members, 0);
1492 while ((m = ao2_iterator_next(&mem_iter))) {
1494 ao2_unlink(q->members, m);
1495 remove_from_interfaces(m->state_interface);
1506 static struct call_queue *load_realtime_queue(const char *queuename)
1508 struct ast_variable *queue_vars;
1509 struct ast_config *member_config = NULL;
1510 struct call_queue *q = NULL, tmpq = {
1514 /* Find the queue in the in-core list first. */
1515 q = ao2_find(queues, &tmpq, OBJ_POINTER);
1517 if (!q || q->realtime) {
1518 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1519 queue operations while waiting for the DB.
1521 This will be two separate database transactions, so we might
1522 see queue parameters as they were before another process
1523 changed the queue and member list as it was after the change.
1524 Thus we might see an empty member list when a queue is
1525 deleted. In practise, this is unlikely to cause a problem. */
1527 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1529 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1530 if (!member_config) {
1531 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1532 ast_variables_destroy(queue_vars);
1538 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1540 ast_config_destroy(member_config);
1542 ast_variables_destroy(queue_vars);
1546 update_realtime_members(q);
1551 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
1553 struct ast_variable *var;
1556 if (!(var = ast_load_realtime("queue_members", "interface", mem->interface, "queue_name", queue_name, NULL)))
1559 if (!strcmp(var->name, "uniqueid"))
1563 if (var && !ast_strlen_zero(var->value)) {
1564 if ((ast_update_realtime("queue_members", "uniqueid", var->value, field, value, NULL)) > -1)
1570 static void update_realtime_members(struct call_queue *q)
1572 struct ast_config *member_config = NULL;
1574 char *interface = NULL;
1575 struct ao2_iterator mem_iter;
1577 if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , NULL))) {
1578 /*This queue doesn't have realtime members*/
1579 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
1585 /* Temporarily set realtime members dead so we can detect deleted ones.*/
1586 mem_iter = ao2_iterator_init(q->members, 0);
1587 while ((m = ao2_iterator_next(&mem_iter))) {
1593 while ((interface = ast_category_browse(member_config, interface))) {
1594 rt_handle_member_record(q, interface,
1595 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1596 ast_variable_retrieve(member_config, interface, "penalty"),
1597 ast_variable_retrieve(member_config, interface, "paused"),
1598 S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface));
1601 /* Delete all realtime members that have been deleted in DB. */
1602 mem_iter = ao2_iterator_init(q->members, 0);
1603 while ((m = ao2_iterator_next(&mem_iter))) {
1605 ao2_unlink(q->members, m);
1606 remove_from_interfaces(m->state_interface);
1612 ast_config_destroy(member_config);
1615 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1617 struct call_queue *q;
1618 struct queue_ent *cur, *prev = NULL;
1622 enum queue_member_status stat;
1624 if (!(q = load_realtime_queue(queuename)))
1630 /* This is our one */
1631 stat = get_member_status(q, qe->max_penalty, qe->min_penalty);
1632 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1633 *reason = QUEUE_JOINEMPTY;
1634 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
1635 *reason = QUEUE_JOINUNAVAIL;
1636 else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1637 *reason = QUEUE_JOINUNAVAIL;
1638 else if (q->maxlen && (q->count >= q->maxlen))
1639 *reason = QUEUE_FULL;
1641 /* There's space for us, put us at the right position inside
1643 * Take into account the priority of the calling user */
1648 /* We have higher priority than the current user, enter
1649 * before him, after all the other users with priority
1650 * higher or equal to our priority. */
1651 if ((!inserted) && (qe->prio > cur->prio)) {
1652 insert_entry(q, prev, qe, &pos);
1659 /* No luck, join at the end of the queue */
1661 insert_entry(q, prev, qe, &pos);
1662 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1663 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1664 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1667 manager_event(EVENT_FLAG_CALL, "Join",
1668 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1670 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1671 S_OR(qe->chan->cid.cid_name, "unknown"),
1672 q->name, qe->pos, q->count, qe->chan->uniqueid );
1673 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1681 static int play_file(struct ast_channel *chan, const char *filename)
1685 ast_stopstream(chan);
1687 res = ast_streamfile(chan, filename, chan->language);
1689 res = ast_waitstream(chan, AST_DIGIT_ANY);
1691 ast_stopstream(chan);
1696 static int valid_exit(struct queue_ent *qe, char digit)
1698 int digitlen = strlen(qe->digits);
1700 /* Prevent possible buffer overflow */
1701 if (digitlen < sizeof(qe->digits) - 2) {
1702 qe->digits[digitlen] = digit;
1703 qe->digits[digitlen + 1] = '\0';
1705 qe->digits[0] = '\0';
1709 /* If there's no context to goto, short-circuit */
1710 if (ast_strlen_zero(qe->context))
1713 /* If the extension is bad, then reset the digits to blank */
1714 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1715 qe->digits[0] = '\0';
1719 /* We have an exact match */
1720 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1721 qe->valid_digits = 1;
1722 /* Return 1 on a successful goto */
1729 static int say_position(struct queue_ent *qe, int ringing)
1731 int res = 0, avgholdmins, avgholdsecs;
1734 /* Let minannouncefrequency seconds pass between the start of each position announcement */
1736 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
1739 /* If either our position has changed, or we are over the freq timer, say position */
1740 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1744 ast_indicate(qe->chan,-1);
1746 ast_moh_stop(qe->chan);
1748 if (qe->parent->announceposition) {
1749 /* Say we're next, if we are */
1751 res = play_file(qe->chan, qe->parent->sound_next);
1757 res = play_file(qe->chan, qe->parent->sound_thereare);
1760 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
1763 res = play_file(qe->chan, qe->parent->sound_calls);
1768 /* Round hold time to nearest minute */
1769 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1771 /* If they have specified a rounding then round the seconds as well */
1772 if (qe->parent->roundingseconds) {
1773 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1774 avgholdsecs *= qe->parent->roundingseconds;
1779 ast_verb(3, "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1781 /* If the hold time is >1 min, if it's enabled, and if it's not
1782 supposed to be only once and we have already said it, say it */
1783 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1784 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1785 res = play_file(qe->chan, qe->parent->sound_holdtime);
1789 if (avgholdmins > 0) {
1790 if (avgholdmins < 2) {
1791 res = play_file(qe->chan, qe->parent->sound_lessthan);
1795 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1799 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1804 res = play_file(qe->chan, qe->parent->sound_minutes);
1808 if (avgholdsecs>0) {
1809 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1813 res = play_file(qe->chan, qe->parent->sound_seconds);
1821 if (qe->parent->announceposition) {
1822 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
1823 qe->chan->name, qe->parent->name, qe->pos);
1825 res = play_file(qe->chan, qe->parent->sound_thanks);
1828 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
1831 /* Set our last_pos indicators */
1833 qe->last_pos_said = qe->pos;
1835 /* Don't restart music on hold if we're about to exit the caller from the queue */
1838 ast_indicate(qe->chan, AST_CONTROL_RINGING);
1840 ast_moh_start(qe->chan, qe->moh, NULL);
1845 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
1849 /* Calculate holdtime using a recursive boxcar filter */
1850 /* Thanks to SRT for this contribution */
1851 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1853 ao2_lock(qe->parent);
1854 oldvalue = qe->parent->holdtime;
1855 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
1856 ao2_unlock(qe->parent);
1860 static void leave_queue(struct queue_ent *qe)
1862 struct call_queue *q;
1863 struct queue_ent *cur, *prev = NULL;
1864 struct penalty_rule *pr_iter;
1867 if (!(q = qe->parent))
1873 for (cur = q->head; cur; cur = cur->next) {
1877 /* Take us out of the queue */
1878 manager_event(EVENT_FLAG_CALL, "Leave",
1879 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1880 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1881 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1882 /* Take us out of the queue */
1884 prev->next = cur->next;
1886 q->head = cur->next;
1887 /* Free penalty rules */
1888 while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list)))
1891 /* Renumber the people after us in the queue based on a new count */
1898 /*If the queue is a realtime queue, check to see if it's still defined in real time*/
1900 if (!ast_load_realtime("queues", "name", q->name, NULL))
1905 /* It's dead and nobody is in it, so kill it */
1906 ao2_unlink(queues, q);
1912 /* Hang up a list of outgoing calls */
1913 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1915 struct callattempt *oo;
1918 /* Hangup any existing lines we have open */
1919 if (outgoing->chan && (outgoing->chan != exception))
1920 ast_hangup(outgoing->chan);
1922 outgoing = outgoing->q_next;
1924 ao2_ref(oo->member, -1);
1929 static int update_status(struct call_queue *q, struct member *member, int status)
1932 struct ao2_iterator mem_iter;
1934 /* Since a reload could have taken place, we have to traverse the list to
1935 be sure it's still valid */
1937 mem_iter = ao2_iterator_init(q->members, 0);
1938 while ((cur = ao2_iterator_next(&mem_iter))) {
1939 if (member != cur) {
1944 cur->status = status;
1945 if (!q->maskmemberstatus) {
1946 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1949 "MemberName: %s\r\n"
1950 "Membership: %s\r\n"
1952 "CallsTaken: %d\r\n"
1956 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static",
1957 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1965 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1967 if (status == AST_CAUSE_BUSY)
1968 status = AST_DEVICE_BUSY;
1969 else if (status == AST_CAUSE_UNREGISTERED)
1970 status = AST_DEVICE_UNAVAILABLE;
1971 else if (status == AST_CAUSE_NOSUCHDRIVER)
1972 status = AST_DEVICE_INVALID;
1974 status = AST_DEVICE_UNKNOWN;
1975 return update_status(q, member, status);
1978 /* traverse all defined queues which have calls waiting and contain this member
1979 return 0 if no other queue has precedence (higher weight) or 1 if found */
1980 static int compare_weight(struct call_queue *rq, struct member *member)
1982 struct call_queue *q;
1985 struct ao2_iterator queue_iter;
1987 /* &qlock and &rq->lock already set by try_calling()
1988 * to solve deadlock */
1989 queue_iter = ao2_iterator_init(queues, 0);
1990 while ((q = ao2_iterator_next(&queue_iter))) {
1991 if (q == rq) { /* don't check myself, could deadlock */
1996 if (q->count && q->members) {
1997 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
1998 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1999 if (q->weight > rq->weight) {
2000 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);
2016 /*! \brief common hangup actions */
2017 static void do_hang(struct callattempt *o)
2020 ast_hangup(o->chan);
2024 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
2026 struct ast_str *buf = ast_str_alloca(len + 1);
2029 if (pbx_builtin_serialize_variables(chan, &buf)) {
2032 /* convert "\n" to "\nVariable: " */
2033 strcpy(vars, "Variable: ");
2036 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
2039 if (tmp[i + 1] == '\0')
2041 if (tmp[i] == '\n') {
2045 ast_copy_string(&(vars[j]), "Variable: ", len - j);
2055 /* there are no channel variables; leave it blank */
2061 /*! \brief Part 2 of ring_one
2063 * Does error checking before attempting to request a channel and call a member. This
2064 * function is only called from ring_one
2066 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
2073 /* on entry here, we know that tmp->chan == NULL */
2074 if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
2075 (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
2076 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
2077 (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
2079 ast_cdr_busy(qe->chan->cdr);
2080 tmp->stillgoing = 0;
2085 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
2086 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
2088 ast_cdr_busy(qe->chan->cdr);
2089 tmp->stillgoing = 0;
2093 if (tmp->member->paused) {
2094 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
2096 ast_cdr_busy(qe->chan->cdr);
2097 tmp->stillgoing = 0;
2100 if (use_weight && compare_weight(qe->parent,tmp->member)) {
2101 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
2103 ast_cdr_busy(qe->chan->cdr);
2104 tmp->stillgoing = 0;
2109 ast_copy_string(tech, tmp->interface, sizeof(tech));
2110 if ((location = strchr(tech, '/')))
2115 /* Request the peer */
2116 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
2117 if (!tmp->chan) { /* If we can't, just go on to the next call */
2119 ast_cdr_busy(qe->chan->cdr);
2120 tmp->stillgoing = 0;
2121 update_dial_status(qe->parent, tmp->member, status);
2123 ao2_lock(qe->parent);
2124 qe->parent->rrpos++;
2126 ao2_unlock(qe->parent);
2131 } else if (status != tmp->oldstatus)
2132 update_dial_status(qe->parent, tmp->member, status);
2134 tmp->chan->appl = "AppQueue";
2135 tmp->chan->data = "(Outgoing Line)";
2136 tmp->chan->whentohangup = 0;
2137 if (tmp->chan->cid.cid_num)
2138 ast_free(tmp->chan->cid.cid_num);
2139 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
2140 if (tmp->chan->cid.cid_name)
2141 ast_free(tmp->chan->cid.cid_name);
2142 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
2143 if (tmp->chan->cid.cid_ani)
2144 ast_free(tmp->chan->cid.cid_ani);
2145 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
2147 /* Inherit specially named variables from parent channel */
2148 ast_channel_inherit_variables(qe->chan, tmp->chan);
2150 /* Presense of ADSI CPE on outgoing channel follows ours */
2151 tmp->chan->adsicpe = qe->chan->adsicpe;
2153 /* Inherit context and extension */
2154 if (!ast_strlen_zero(qe->chan->macrocontext))
2155 ast_copy_string(tmp->chan->dialcontext, qe->chan->macrocontext, sizeof(tmp->chan->dialcontext));
2157 ast_copy_string(tmp->chan->dialcontext, qe->chan->context, sizeof(tmp->chan->dialcontext));
2158 if (!ast_strlen_zero(qe->chan->macroexten))
2159 ast_copy_string(tmp->chan->exten, qe->chan->macroexten, sizeof(tmp->chan->exten));
2161 ast_copy_string(tmp->chan->exten, qe->chan->exten, sizeof(tmp->chan->exten));
2163 /* Place the call, but don't wait on the answer */
2164 if ((res = ast_call(tmp->chan, location, 0))) {
2165 /* Again, keep going even if there's an error */
2166 ast_debug(1, "ast call on peer returned %d\n", res);
2167 ast_verb(3, "Couldn't call %s\n", tmp->interface);
2171 } else if (qe->parent->eventwhencalled) {
2174 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
2176 "AgentCalled: %s\r\n"
2178 "ChannelCalling: %s\r\n"
2179 "DestinationChannel: %s\r\n"
2180 "CallerIDNum: %s\r\n"
2181 "CallerIDName: %s\r\n"
2186 qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
2187 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
2188 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
2189 qe->chan->context, qe->chan->exten, qe->chan->priority,
2190 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2191 ast_verb(3, "Called %s\n", tmp->interface);
2197 /*! \brief find the entry with the best metric, or NULL */
2198 static struct callattempt *find_best(struct callattempt *outgoing)
2200 struct callattempt *best = NULL, *cur;
2202 for (cur = outgoing; cur; cur = cur->q_next) {
2203 if (cur->stillgoing && /* Not already done */
2204 !cur->chan && /* Isn't already going */
2205 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
2213 /*! \brief Place a call to a queue member
2215 * Once metrics have been calculated for each member, this function is used
2216 * to place a call to the appropriate member (or members). The low-level
2217 * channel-handling and error detection is handled in ring_entry
2219 * Returns 1 if a member was called successfully, 0 otherwise
2221 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
2226 struct callattempt *best = find_best(outgoing);
2228 ast_debug(1, "Nobody left to try ringing in queue\n");
2231 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2232 struct callattempt *cur;
2233 /* Ring everyone who shares this best metric (for ringall) */
2234 for (cur = outgoing; cur; cur = cur->q_next) {
2235 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
2236 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
2237 ret |= ring_entry(qe, cur, busies);
2241 /* Ring just the best channel */
2242 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
2243 ret = ring_entry(qe, best, busies);
2250 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
2252 struct callattempt *best = find_best(outgoing);
2255 /* Ring just the best channel */
2256 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2257 qe->parent->rrpos = best->metric % 1000;
2259 /* Just increment rrpos */
2260 if (qe->parent->wrapped) {
2261 /* No more channels, start over */
2262 qe->parent->rrpos = 0;
2264 /* Prioritize next entry */
2265 qe->parent->rrpos++;
2268 qe->parent->wrapped = 0;
2273 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
2275 struct callattempt *best = find_best(outgoing);
2278 /* Ring just the best channel */
2279 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2280 qe->linpos = best->metric % 1000;
2282 /* Just increment rrpos */
2283 if (qe->linwrapped) {
2284 /* No more channels, start over */
2287 /* Prioritize next entry */
2296 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
2301 /* Get the current time */
2304 /* Check to see if it is time to announce */
2305 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
2308 /* Stop the music on hold so we can play our own file */
2310 ast_indicate(qe->chan,-1);
2312 ast_moh_stop(qe->chan);
2314 ast_verb(3, "Playing periodic announcement\n");
2316 /* Check to make sure we have a sound file. If not, reset to the first sound file */
2317 if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS ||
2318 !qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound] ||
2319 ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str)) {
2320 qe->last_periodic_announce_sound = 0;
2323 /* play the announcement */
2324 res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str);
2326 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
2329 /* Resume Music on Hold if the caller is going to stay in the queue */
2332 ast_indicate(qe->chan, AST_CONTROL_RINGING);
2334 ast_moh_start(qe->chan, qe->moh, NULL);
2337 /* update last_periodic_announce_time */
2338 qe->last_periodic_announce_time = now;
2340 /* Update the current periodic announcement to the next announcement */
2341 qe->last_periodic_announce_sound++;
2346 static void record_abandoned(struct queue_ent *qe)
2348 ao2_lock(qe->parent);
2349 set_queue_variables(qe);
2350 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
2354 "OriginalPosition: %d\r\n"
2356 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
2358 qe->parent->callsabandoned++;
2359 ao2_unlock(qe->parent);
2362 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
2363 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
2365 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
2366 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
2367 if (qe->parent->autopause) {
2368 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
2369 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
2371 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
2377 #define AST_MAX_WATCHERS 256
2378 /*! \brief Wait for a member to answer the call
2380 * \param[in] qe the queue_ent corresponding to the caller in the queue
2381 * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
2382 * \param[in] to the amount of time (in milliseconds) to wait for a response
2383 * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
2384 * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
2385 * \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
2386 * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
2388 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
2390 const char *queue = qe->parent->name;
2391 struct callattempt *o, *start = NULL, *prev = NULL;
2393 int numbusies = prebusies;
2397 struct ast_frame *f;
2398 struct callattempt *peer = NULL;
2399 struct ast_channel *winner;
2400 struct ast_channel *in = qe->chan;
2402 char membername[80] = "";
2406 struct callattempt *epollo;
2409 starttime = (long) time(NULL);
2411 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2413 ast_poll_channel_add(in, epollo->chan);
2417 while (*to && !peer) {
2418 int numlines, retry, pos = 1;
2419 struct ast_channel *watchers[AST_MAX_WATCHERS];
2423 for (retry = 0; retry < 2; retry++) {
2425 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
2426 if (o->stillgoing) { /* Keep track of important channels */
2429 watchers[pos++] = o->chan;
2433 prev->call_next = o;
2439 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
2440 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
2442 /* On "ringall" strategy we only move to the next penalty level
2443 when *all* ringing phones are done in the current penalty level */
2444 ring_one(qe, outgoing, &numbusies);
2447 if (pos == 1 /* not found */) {
2448 if (numlines == (numbusies + numnochan)) {
2449 ast_debug(1, "Everyone is busy at this time\n");
2451 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
2456 winner = ast_waitfor_n(watchers, pos, to);
2457 for (o = start; o; o = o->call_next) {
2458 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
2460 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2463 } else if (o->chan && (o->chan == winner)) {
2465 ast_copy_string(on, o->member->interface, sizeof(on));
2466 ast_copy_string(membername, o->member->membername, sizeof(membername));
2468 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
2469 ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
2474 } else if (!ast_strlen_zero(o->chan->call_forward)) {
2479 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
2480 if ((stuff = strchr(tmpchan, '/'))) {
2484 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
2488 /* Before processing channel, go ahead and check for forwarding */
2489 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2490 /* Setup parameters */
2491 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2492 if (status != o->oldstatus)
2493 update_dial_status(qe->parent, o->member, status);
2495 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
2499 ast_channel_inherit_variables(in, o->chan);
2500 ast_channel_datastore_inherit(in, o->chan);
2501 if (o->chan->cid.cid_num)
2502 ast_free(o->chan->cid.cid_num);
2503 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
2505 if (o->chan->cid.cid_name)
2506 ast_free(o->chan->cid.cid_name);
2507 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
2509 ast_string_field_set(o->chan, accountcode, in->accountcode);
2510 o->chan->cdrflags = in->cdrflags;
2512 if (in->cid.cid_ani) {
2513 if (o->chan->cid.cid_ani)
2514 ast_free(o->chan->cid.cid_ani);
2515 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
2517 if (o->chan->cid.cid_rdnis)
2518 ast_free(o->chan->cid.cid_rdnis);
2519 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
2520 if (ast_call(o->chan, tmpchan, 0)) {
2521 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
2526 /* Hangup the original channel now, in case we needed it */
2530 f = ast_read(winner);
2532 if (f->frametype == AST_FRAME_CONTROL) {
2533 switch (f->subclass) {
2534 case AST_CONTROL_ANSWER:
2535 /* This is our guy if someone answered. */
2537 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2541 case AST_CONTROL_BUSY:
2542 ast_verb(3, "%s is busy\n", o->chan->name);
2544 ast_cdr_busy(in->cdr);
2546 endtime = (long) time(NULL);
2547 endtime -= starttime;
2548 rna(endtime*1000, qe, on, membername);
2549 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2550 if (qe->parent->timeoutrestart)
2552 ring_one(qe, outgoing, &numbusies);
2556 case AST_CONTROL_CONGESTION:
2557 ast_verb(3, "%s is circuit-busy\n", o->chan->name);
2559 ast_cdr_busy(in->cdr);
2560 endtime = (long) time(NULL);
2561 endtime -= starttime;
2562 rna(endtime*1000, qe, on, membername);
2564 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2565 if (qe->parent->timeoutrestart)
2567 ring_one(qe, outgoing, &numbusies);
2571 case AST_CONTROL_RINGING:
2572 ast_verb(3, "%s is ringing\n", o->chan->name);
2574 case AST_CONTROL_OFFHOOK:
2575 /* Ignore going off hook */
2578 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
2583 endtime = (long) time(NULL) - starttime;
2584 rna(endtime * 1000, qe, on, membername);
2586 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2587 if (qe->parent->timeoutrestart)
2589 ring_one(qe, outgoing, &numbusies);
2596 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2604 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2605 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
2610 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass)) {
2611 ast_verb(3, "User pressed digit: %c\n", f->subclass);
2613 *digit = f->subclass;
2620 for (o = start; o; o = o->call_next)
2621 rna(orig, qe, o->interface, o->member->membername);
2626 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2628 ast_poll_channel_del(in, epollo->chan);
2634 /*! \brief Check if we should start attempting to call queue members
2636 * The behavior of this function is dependent first on whether autofill is enabled
2637 * and second on whether the ring strategy is ringall. If autofill is not enabled,
2638 * then return true if we're the head of the queue. If autofill is enabled, then
2639 * we count the available members and see if the number of available members is enough
2640 * that given our position in the queue, we would theoretically be able to connect to
2641 * one of those available members
2643 static int is_our_turn(struct queue_ent *qe)
2645 struct queue_ent *ch;
2651 if (!qe->parent->autofill) {
2652 /* Atomically read the parent head -- does not need a lock */
2653 ch = qe->parent->head;
2654 /* If we are now at the top of the head, break out */
2656 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2659 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2664 /* This needs a lock. How many members are available to be served? */
2665 ao2_lock(qe->parent);
2667 ch = qe->parent->head;
2669 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2670 ast_debug(1, "Even though there may be multiple members available, the strategy is ringall so only the head call is allowed in\n");
2673 struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
2674 while ((cur = ao2_iterator_next(&mem_iter))) {
2675 switch (cur->status) {
2676 case AST_DEVICE_NOT_INUSE:
2677 case AST_DEVICE_UNKNOWN:
2686 ast_debug(1, "There are %d available members.\n", avl);
2688 while ((idx < avl) && (ch) && (ch != qe)) {
2694 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2695 if (ch && idx < avl) {
2696 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2699 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2703 ao2_unlock(qe->parent);
2708 static void update_qe_rule(struct queue_ent *qe)
2710 int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
2711 int min_penalty = qe->pr->min_relative ? qe->min_penalty + qe->pr->min_value : qe->pr->min_value;
2712 char max_penalty_str[20], min_penalty_str[20];
2713 /* a relative change to the penalty could put it below 0 */
2714 if (max_penalty < 0)
2716 if (min_penalty < 0)
2718 if (min_penalty > max_penalty)
2719 min_penalty = max_penalty;
2720 snprintf(max_penalty_str, sizeof(max_penalty_str) - 1, "%d", max_penalty);
2721 snprintf(min_penalty_str, sizeof(min_penalty_str) - 1, "%d", min_penalty);
2722 pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
2723 pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
2724 qe->max_penalty = max_penalty;
2725 qe->min_penalty = min_penalty;
2726 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);
2727 qe->pr = AST_LIST_NEXT(qe->pr, list);
2730 /*! \brief The waiting areas for callers who are not actively calling members
2732 * This function is one large loop. This function will return if a caller
2733 * either exits the queue or it becomes that caller's turn to attempt calling
2734 * queue members. Inside the loop, we service the caller with periodic announcements,
2735 * holdtime announcements, etc. as configured in queues.conf
2737 * \retval 0 if the caller's turn has arrived
2738 * \retval -1 if the caller should exit the queue.
2740 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2744 /* This is the holding pen for callers 2 through maxlen */
2746 enum queue_member_status stat;
2748 if (is_our_turn(qe))
2751 /* If we have timed out, break out */
2752 if (qe->expire && (time(NULL) > qe->expire)) {
2753 *reason = QUEUE_TIMEOUT;
2757 stat = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty);
2759 /* leave the queue if no agents, if enabled */
2760 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2761 *reason = QUEUE_LEAVEEMPTY;
2762 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2767 /* leave the queue if no reachable agents, if enabled */
2768 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
2769 *reason = QUEUE_LEAVEUNAVAIL;
2770 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2774 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2775 *reason = QUEUE_LEAVEUNAVAIL;
2776 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2781 /* Make a position announcement, if enabled */
2782 if (qe->parent->announcefrequency &&
2783 (res = say_position(qe,ringing)))
2786 /* Make a periodic announcement, if enabled */
2787 if (qe->parent->periodicannouncefrequency &&
2788 (res = say_periodic_announcement(qe,ringing)))
2791 /* see if we need to move to the next penalty level for this queue */
2792 while (qe->pr && ((time(NULL) - qe->start) > qe->pr->time)) {
2796 /* Wait a second before checking again */
2797 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
2798 if (res > 0 && !valid_exit(qe, res))
2808 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl)
2811 struct call_queue *qtmp;
2812 struct ao2_iterator queue_iter;
2814 if (shared_lastcall) {
2815 queue_iter = ao2_iterator_init(queues, 0);
2816 while ((qtmp = ao2_iterator_next(&queue_iter))) {
2818 if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
2819 time(&mem->lastcall);
2829 time(&member->lastcall);
2831 member->lastqueue = q;
2835 q->callscompleted++;
2836 if (callcompletedinsl)
2837 q->callscompletedinsl++;
2842 /*! \brief Calculate the metric of each member in the outgoing callattempts
2844 * A numeric metric is given to each member depending on the ring strategy used
2845 * by the queue. Members with lower metrics will be called before members with
2848 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2850 if ((qe->max_penalty && (mem->penalty > qe->max_penalty)) || (qe->min_penalty && (mem->penalty < qe->min_penalty)))
2853 switch (q->strategy) {
2854 case QUEUE_STRATEGY_RINGALL:
2855 /* Everyone equal, except for penalty */
2856 tmp->metric = mem->penalty * 1000000;
2858 case QUEUE_STRATEGY_LINEAR:
2859 if (pos < qe->linpos) {
2860 tmp->metric = 1000 + pos;
2862 if (pos > qe->linpos)
2863 /* Indicate there is another priority */
2867 tmp->metric += mem->penalty * 1000000;
2869 case QUEUE_STRATEGY_RRMEMORY:
2870 if (pos < q->rrpos) {
2871 tmp->metric = 1000 + pos;
2874 /* Indicate there is another priority */
2878 tmp->metric += mem->penalty * 1000000;
2880 case QUEUE_STRATEGY_RANDOM:
2881 tmp->metric = ast_random() % 1000;
2882 tmp->metric += mem->penalty * 1000000;
2884 case QUEUE_STRATEGY_WRANDOM:
2885 tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
2887 case QUEUE_STRATEGY_FEWESTCALLS:
2888 tmp->metric = mem->calls;
2889 tmp->metric += mem->penalty * 1000000;
2891 case QUEUE_STRATEGY_LEASTRECENT:
2895 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2896 tmp->metric += mem->penalty * 1000000;
2899 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2905 enum agent_complete_reason {
2911 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
2912 const struct ast_channel *peer, const struct member *member, time_t callstart,
2913 char *vars, size_t vars_len, enum agent_complete_reason rsn)
2915 const char *reason = NULL; /* silence dumb compilers */
2917 if (!qe->parent->eventwhencalled)
2928 reason = "transfer";
2932 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2937 "MemberName: %s\r\n"
2942 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2943 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
2944 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
2946 /*! \brief A large function which calls members, updates statistics, and bridges the caller and a member
2948 * Here is the process of this function
2949 * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
2950 * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
2951 * iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
2952 * member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also
2953 * during each iteration, we call calc_metric to determine which members should be rung when.
2954 * 3. Call ring_one to place a call to the appropriate member(s)
2955 * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
2956 * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
2957 * 6. Start the monitor or mixmonitor if the option is set
2958 * 7. Remove the caller from the queue to allow other callers to advance
2959 * 8. Bridge the call.
2960 * 9. Do any post processing after the call has disconnected.
2962 * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
2963 * \param[in] options the options passed as the third parameter to the Queue() application
2964 * \param[in] url the url passed as the fourth parameter to the Queue() application
2965 * \param[in,out] tries the number of times we have tried calling queue members
2966 * \param[out] noption set if the call to Queue() has the 'n' option set.
2967 * \param[in] agi the agi passed as the fifth parameter to the Queue() application
2968 * \param[in] macro the macro passed as the sixth parameter to the Queue() application
2969 * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
2970 * \param[in] ringing 1 if the 'r' option is set, otherwise 0
2972 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)
2975 struct callattempt *outgoing = NULL; /* the list of calls we are building */
2977 char oldexten[AST_MAX_EXTENSION]="";
2978 char oldcontext[AST_MAX_CONTEXT]="";
2979 char queuename[256]="";
2980 char interfacevar[256]="";
2981 struct ast_channel *peer;
2982 struct ast_channel *which;
2983 struct callattempt *lpeer;
2984 struct member *member;
2985 struct ast_app *app;
2986 int res = 0, bridge = 0;
2989 char *announce = NULL;
2992 time_t now = time(NULL);
2993 struct ast_bridge_config bridge_config;
2994 char nondataquality = 1;
2995 char *agiexec = NULL;
2996 char *macroexec = NULL;
2997 char *gosubexec = NULL;
2999 const char *monitorfilename;
3000 const char *monitor_exec;
3001 const char *monitor_options;
3002 char tmpid[256], tmpid2[256];
3003 char meid[1024], meid2[1024];
3004 char mixmonargs[1512];
3005 struct ast_app *mixmonapp = NULL;
3008 int forwardsallowed = 1;
3009 int callcompletedinsl;
3010 struct ao2_iterator memi;
3011 struct ast_datastore *datastore;
3013 ast_channel_lock(qe->chan);
3014 datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
3015 ast_channel_unlock(qe->chan);
3017 memset(&bridge_config, 0, sizeof(bridge_config));
3022 for (; options && *options; options++)
3025 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
3028 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
3031 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
3034 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
3040 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
3043 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
3046 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
3049 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
3052 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR)
3055 *tries = qe->parent->membercount;
3059 forwardsallowed = 0;
3062 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
3065 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
3070 /* Hold the lock while we setup the outgoing calls */
3073 ao2_lock(qe->parent);
3074 ast_debug(1, "%s is trying to call a queue member.\n",
3076 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
3077 if (!ast_strlen_zero(qe->announce))
3078 announce = qe->announce;
3079 if (!ast_strlen_zero(announceoverride))
3080 announce = announceoverride;
3082 memi = ao2_iterator_init(qe->parent->members, 0);
3083 while ((cur = ao2_iterator_next(&memi))) {
3084 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
3085 struct ast_dialed_interface *di;
3086 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
3089 ao2_unlock(qe->parent);
3095 if (!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) {
3097 ao2_unlock(qe->parent);
3103 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3104 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
3106 ao2_unlock(&qe->parent);
3112 datastore->data = dialed_interfaces;
3113 AST_LIST_HEAD_INIT(dialed_interfaces);
3115 ast_channel_lock(qe->chan);
3116 ast_channel_datastore_add(qe->chan, datastore);
3117 ast_channel_unlock(qe->chan);
3119 dialed_interfaces = datastore->data;
3121 AST_LIST_LOCK(dialed_interfaces);
3122 AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
3123 if (!strcasecmp(cur->interface, di->interface)) {
3124 ast_log(LOG_DEBUG, "Skipping dialing interface '%s' since it has already been dialed\n",
3129 AST_LIST_UNLOCK(dialed_interfaces);
3136 /* It is always ok to dial a Local interface. We only keep track of
3137 * which "real" interfaces have been dialed. The Local channel will
3138 * inherit this list so that if it ends up dialing a real interface,
3139 * it won't call one that has already been called. */
3140 if (strncasecmp(cur->interface, "Local/", 6)) {
3141 if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
3143 ao2_unlock(qe->parent);
3149 strcpy(di->interface, cur->interface);
3151 AST_LIST_LOCK(dialed_interfaces);
3152 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
3153 AST_LIST_UNLOCK(dialed_interfaces);
3156 tmp->stillgoing = -1;
3158 tmp->oldstatus = cur->status;
3159 tmp->lastcall = cur->lastcall;
3160 tmp->lastqueue = cur->lastqueue;
3161 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
3162 /* Special case: If we ring everyone, go ahead and ring them, otherwise
3163 just calculate their metric for the appropriate strategy */
3164 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
3165 /* Put them in the list of outgoing thingies... We're ready now.
3166 XXX If we're forcibly removed, these outgoing calls won't get
3168 tmp->q_next = outgoing;
3170 /* If this line is up, don't try anybody else */
3171 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
3178 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
3179 to = (qe->expire - now) * 1000;
3181 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
3184 ring_one(qe, outgoing, &numbusies);
3185 ao2_unlock(qe->parent);
3188 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
3190 ast_channel_datastore_remove(qe->chan, datastore);
3191 ast_channel_datastore_free(datastore);
3193 ao2_lock(qe->parent);
3194 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
3195 store_next_rr(qe, outgoing);
3197 if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
3198 store_next_lin(qe, outgoing);
3200 ao2_unlock(qe->parent);
3201 peer = lpeer ? lpeer->chan : NULL;
3205 /* Must gotten hung up */
3208 /* User exited by pressing a digit */
3212 ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
3213 } else { /* peer is valid */
3214 /* Ah ha! Someone answered within the desired timeframe. Of course after this
3215 we will always return with -1 so that it is hung up properly after the
3218 if (!strcmp(qe->chan->tech->type, "Zap"))
3219 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
3220 if (!strcmp(peer->tech->type, "Zap"))
3221 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
3222 /* Update parameters for the queue */
3224 recalc_holdtime(qe, (now - qe->start));
3225 ao2_lock(qe->parent);
3226 callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
3227 ao2_unlock(qe->parent);
3228 member = lpeer->member;
3229 /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
3231 hangupcalls(outgoing, peer);
3233 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
3236 res2 = ast_autoservice_start(qe->chan);
3238 if (qe->parent->memberdelay) {
3239 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
3240 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
3242 if (!res2 && announce) {
3243 play_file(peer, announce);
3245 if (!res2 && qe->parent->reportholdtime) {
3246 if (!play_file(peer, qe->parent->sound_reporthold)) {
3250 holdtime = abs((now - qe->start) / 60);
3252 play_file(peer, qe->parent->sound_lessthan);
3253 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
3255 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
3256 play_file(peer, qe->parent->sound_minutes);
3260 res2 |= ast_autoservice_stop(qe->chan);
3261 if (ast_check_hangup(peer)) {
3262 /* Agent must have hung up */
3263 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
3264 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
3265 record_abandoned(qe);
3266 if (qe->parent->eventwhencalled)
3267 manager_event(EVENT_FLAG_AGENT, "AgentDump",
3272 "MemberName: %s\r\n"
3274 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
3275 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3277 ao2_ref(member, -1);
3280 /* Caller must have hung up just before being connected*/
3281 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
3282 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
3283 record_abandoned(qe);
3285 ao2_ref(member, -1);
3289 /* Stop music on hold */
3291 ast_indicate(qe->chan,-1);
3293 ast_moh_stop(qe->chan);
3294 /* If appropriate, log that we have a destination channel */
3296 ast_cdr_setdestchan(qe->chan->cdr, peer->name);
3297 /* Make sure channels are compatible */
3298 res = ast_channel_make_compatible(qe->chan, peer);
3300 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
3301 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
3302 record_abandoned(qe);
3304 ao2_ref(member, -1);
3308 /* Play announcement to the caller telling it's his turn if defined */
3309 if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
3310 if (play_file(qe->chan, qe->parent->sound_callerannounce))
3311 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
3314 ao2_lock(qe->parent);
3315 /* if setinterfacevar is defined, make member variables available to the channel */
3316 /* use pbx_builtin_setvar to set a load of variables with one call */
3317 if (qe->parent->setinterfacevar) {
3318 snprintf(interfacevar,sizeof(interfacevar), "MEMBERINTERFACE=%s|MEMBERNAME=%s|MEMBERCALLS=%d|MEMBERLASTCALL=%ld|MEMBERPENALTY=%d|MEMBERDYNAMIC=%d|MEMBERREALTIME=%d",
3319 member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
3320 pbx_builtin_setvar(qe->chan, interfacevar);
3323 /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
3324 /* use pbx_builtin_setvar to set a load of variables with one call */
3325 if (qe->parent->setqueueentryvar) {
3326 snprintf(interfacevar,sizeof(interfacevar), "QEHOLDTIME=%ld|QEORIGINALPOS=%d",
3327 (long) time(NULL) - qe->start, qe->opos);
3328 pbx_builtin_setvar(qe->chan, interfacevar);
3331 /* try to set queue variables if configured to do so*/
3332 set_queue_variables(qe);
3333 ao2_unlock(qe->parent);
3335 /* Begin Monitoring */
3336 if (qe->parent->monfmt && *qe->parent->monfmt) {
3337 if (!qe->parent->montype) {
3338 ast_debug(1, "Starting Monitor as requested.\n");
3339 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
3340 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
3344 if (monitorfilename)
3345 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
3346 else if (qe->chan->cdr)
3347 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1, X_REC_IN | X_REC_OUT);
3349 /* Last ditch effort -- no CDR, make up something */
3350 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
3351 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
3354 ast_debug(1, "Starting MixMonitor as requested.\n");
3355 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
3356 if (!monitorfilename) {
3358 ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid));
3360 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
3362 const char *m = monitorfilename;
3363 for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
3366 if (*(m + 1) == '{')
3378 if (p == tmpid2 + sizeof(tmpid2))
3379 tmpid2[sizeof(tmpid2) - 1] = '\0';